<?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: Swapnil M Mane</title>
    <description>The latest articles on Forem by Swapnil M Mane (@swapnilmmane).</description>
    <link>https://forem.com/swapnilmmane</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%2F662344%2F5eed85f6-ba1e-41b1-949e-eb6eddf7fd77.jpeg</url>
      <title>Forem: Swapnil M Mane</title>
      <link>https://forem.com/swapnilmmane</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/swapnilmmane"/>
    <language>en</language>
    <item>
      <title>Learn How to Use Lambda Layers by Building an Image Resize Function Using Sharp</title>
      <dc:creator>Swapnil M Mane</dc:creator>
      <pubDate>Wed, 04 May 2022 08:18:45 +0000</pubDate>
      <link>https://forem.com/webiny/learn-how-to-use-lambda-layers-by-building-an-image-resize-function-using-sharp-bj4</link>
      <guid>https://forem.com/webiny/learn-how-to-use-lambda-layers-by-building-an-image-resize-function-using-sharp-bj4</guid>
      <description>&lt;p&gt;Lambda Layer is a true gem in the Lambda function realm. It provides a convenient way to package your libraries and other dependencies that can be used with the Lambda functions. Our open-source project, &lt;a href="https://github.com/webiny/webiny-js/"&gt;Webiny&lt;/a&gt; which has 50k+ downloads and 5.5k stars on GitHub uses Lambda layers. It helps us reduce our Lambda function size by 12 MB and enable us to share the image processing library &lt;a href="https://sharp.pixelplumbing.com/"&gt;sharp&lt;/a&gt; across all the Webiny deployments.&lt;/p&gt;

&lt;p&gt;By the time you finish reading this article, you will know how to create and use Lambda layers. As an example, we will create a sharp library Layer and use it in a Lambda function to create thumbnail images.&lt;br&gt;
In this tutorial, we will create a Lambda function that will create a thumbnail image using the &lt;code&gt;sharp&lt;/code&gt; library. This library will be packaged into the Lambda function using a &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-concepts.html#gettingstarted-concepts-layer"&gt;Lambda Layer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The workflow will be like this, for each image file uploaded to an S3 bucket (source bucket), the lambda function will be invoked. It will read the image object from the source S3 bucket, create a thumbnail image, and save it to the target S3 bucket.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AWS account - To use various AWS services, you will need an AWS account. Please follow &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/create-and-activate-aws-account"&gt; this link&lt;/a&gt; to create an AWS account.&lt;/li&gt;
&lt;li&gt;AWS command line - We will use the AWS command line for creating Lambda Function and Lambda Layer. The AWS CLI installation guide is available &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1 - Create two S3 buckets
&lt;/h2&gt;

&lt;p&gt;Let’s start by creating two buckets, the source and the target. As mentioned earlier, for each image file uploaded to a source bucket, the Lambda function will create a corresponding thumbnail image and save it in the target S3 bucket.&lt;/p&gt;

&lt;p&gt;Please follow these steps to create S3 buckets.&lt;/p&gt;

&lt;p&gt;1.) Open the &lt;a href="https://console.aws.amazon.com/s3"&gt;Amazon S3 console&lt;/a&gt;.&lt;br&gt;
2.) &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html"&gt;Create two S3 buckets&lt;/a&gt; - source and target.&lt;/p&gt;

&lt;p&gt;The target bucket name should be &lt;code&gt;source-bucket-name&lt;/code&gt; plus suffixed by &lt;code&gt;-resized&lt;/code&gt; .  For example, if the source bucket is named &lt;code&gt;mybucket&lt;/code&gt; then the target bucket should be named as &lt;code&gt;mybucket-resized&lt;/code&gt;. Please follow this naming convention because we will be using this naming logic in the Lambda function.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2 - Create the IAM policy
&lt;/h2&gt;

&lt;p&gt;Now let’s create an IAM policy that specifies the permissions for the Lambda function. The Lambda function must have permission for the following operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get the object from the source S3 bucket.&lt;/li&gt;
&lt;li&gt;Put the resized object into the target S3 bucket.&lt;/li&gt;
&lt;li&gt;Write logs to Amazon CloudWatch Logs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  To create an IAM policy
&lt;/h3&gt;

&lt;p&gt;1.) Open the &lt;a href="https://console.aws.amazon.com/iam/home#/policies"&gt;Policies page&lt;/a&gt; in the IAM console.&lt;br&gt;
2.) Choose &lt;strong&gt;Create policy&lt;/strong&gt;.&lt;br&gt;
3.) Choose the &lt;strong&gt;JSON&lt;/strong&gt; tab, and then paste the following policy. Be sure to replace &lt;code&gt;mybucket&lt;/code&gt; with the name of the source bucket that you created previously.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:PutLogEvents"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:CreateLogGroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"logs:CreateLogStream"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:logs:*:*:*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::mybucket/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::mybucket-resized/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.) Choose &lt;strong&gt;Next: Tags&lt;/strong&gt;.&lt;br&gt;
5.) Choose &lt;strong&gt;Next: Review&lt;/strong&gt;.&lt;br&gt;
6.) Under &lt;strong&gt;Review policy&lt;/strong&gt;, for &lt;strong&gt;Name&lt;/strong&gt;, enter &lt;code&gt;AWSLambdaS3Policy&lt;/code&gt;.&lt;br&gt;
7.) Choose &lt;strong&gt;Create policy&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3 - Create the execution role
&lt;/h2&gt;

&lt;p&gt;Create the &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html"&gt;execution role&lt;/a&gt; that gives your Lambda function permissions to access AWS resources.&lt;/p&gt;
&lt;h3&gt;
  
  
  To create an execution role
&lt;/h3&gt;

&lt;p&gt;1.) Open the &lt;a href="https://console.aws.amazon.com/iam/home#/roles"&gt;Roles page&lt;/a&gt; in the IAM console.&lt;br&gt;
2.) Choose &lt;strong&gt;Create role&lt;/strong&gt;.&lt;br&gt;
3.) Create a role with the following properties:&lt;br&gt;
    - &lt;strong&gt;Trusted entity type&lt;/strong&gt; – AWS Service (Allow AWS services like EC2, Lambda, or others to perform actions in this account.)&lt;br&gt;
    - &lt;strong&gt;Use case&lt;/strong&gt; - Lambda (Allows Lambda functions to call AWS services on your behalf.)&lt;br&gt;
    - &lt;strong&gt;Permissions policy&lt;/strong&gt; – &lt;strong&gt;AWSLambdaS3Policy&lt;/strong&gt;&lt;br&gt;
    - &lt;strong&gt;Role name&lt;/strong&gt; – &lt;code&gt;lambda-s3-role&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4 - Create a sharp Lambda Layer
&lt;/h2&gt;

&lt;p&gt;Here comes the special part of this tutorial. We will create the &lt;a href="https://sharp.pixelplumbing.com/install#aws-lambda"&gt;sharp&lt;/a&gt; Lambda Layer in this section.&lt;/p&gt;

&lt;p&gt;You will perform this part of the tutorial on your machine. Please ensure you have &lt;code&gt;npm&lt;/code&gt; installed (we will need the &lt;code&gt;npm&lt;/code&gt; to install the &lt;code&gt;sharp&lt;/code&gt; package).&lt;/p&gt;

&lt;p&gt;1.) Create a directory with the name &lt;code&gt;nodejs&lt;/code&gt;.&lt;br&gt;
2.) Install the &lt;code&gt;sharp&lt;/code&gt; dependency in the &lt;code&gt;nodejs&lt;/code&gt; directory by running the following commands:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SHARP_IGNORE_GLOBAL_LIBVIPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;x64 &lt;span class="nt"&gt;--platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux sharp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this step, you will get the following directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nodejs
|- node_modules
|- package-lock.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3.) Create a &lt;code&gt;.zip&lt;/code&gt; file archive of the &lt;code&gt;nodejs&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zip &lt;span class="nt"&gt;-r&lt;/span&gt; nodejs.zip nodejs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.) Now let’s publish the Layer. Run the following command to create and publish the Layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda publish-layer-version &lt;span class="nt"&gt;--layer-name&lt;/span&gt; sharp &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"Sharp dependency for image transformation"&lt;/span&gt; &lt;span class="nt"&gt;--zip-file&lt;/span&gt; fileb://nodejs.zip &lt;span class="nt"&gt;--compatible-runtimes&lt;/span&gt; &lt;span class="s2"&gt;"nodejs14.x"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; &lt;span class="s2"&gt;"json"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After successful execution of the command above, you will see an output similar to this one.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Please note the &lt;code&gt;LayerVersionArn&lt;/code&gt;, we will use it while creating the Lambda function.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://prod-04-2014-layers.s3.us-east-1.amazonaws.com/snapshots/400803493251/sharp-539dd937-e29c-4418-bb52-2089f3945afc?versionId=4AMhQSZjY3uw3WI85Jcbf7j7Wj1x1X9i&amp;amp;X-Amz-Security-Token=IQoJb3JpZ2luX2VjEJz%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLWVhc3QtMSJHMEUCIQDu5lMXWxGc7ydyD6HbmtJk2tnqLLxfRbCYqP7tAwi8wAIgAt3KpyhdECs9I7a2mSGNPjk1n4fq1BKjA7iOmBxOquUq%2BgMIRBAAGgw3NDk2Nzg5MDI4MzkiDOj9vGzyeEXkicvNUirXA9YvAlIvZPE3WdpgIYp51YCl28ISR4eL93paFfqBC0IguHOz%2BctOG2P5MwSc2Vj10UVBUBE4qTiGXYTbB3Gk4jCzTvgDEN90fXdMqQYWXCd8zDpq6OIcZ59qVTQPIFdjo2JZ8U3Tfu68BkIynFNLIiX4Y2WvBqxpJoFUlrmOcU4%2FtuXhSmiW6E7xyQus%2F%2BTq3A2n7JaJ2XgKOKPyINyOOBD3ZsonHjiZw0Djtjk7IgvwMjWVLb6Gn73c%2BG9bLKsHHW7aUnRaNEYSdhWejPpz1QEUlcOKpAkLI87kAgTMPCsljZMujUgWxozAth76hWebjXoE7OHUFx870jscKhpMH2DfJhaOCOsmyme69jpqc4%2FEN6jT2WGjIG42xlfUnxB90DpNBjkPguXFyghOHFlhR07bp9Rom0oW1XOriN9jnbxSZqyQsqDFwbrua4oKtOcJJrzDnUGmhKAlWPMkwE81wDyxXSB%2BGYlYQb%2F%2BXScqvqsieBtIpN5KOfAlB0VuoN17gi5BFXsP5ePaGeJPZ5MJ9COQtm6nXdvclUc8ENc0xPfw0l0485%2BVWe%2BzME%2FIIB0Sclg8TuyNSNcqrSxVxb7VVZMZfFrmMpXpU2FD1chXDGTv1tOP3x%2BthjDLvtWSBjqlATnNWnlBoAfJJE7C6ZqVOgRZU4EvDCpLchTmHT%2F99LoBvqYUU0qospR1VT4pGKtfBBEuNGgg9%2F8Dkj6l0q7p62mlxwt%2BENpVp2QOczzj6CDCjMg1E6jnsVGNzCoPeYiEEx8q6LBM51EOMcm2sSSVjNeVNRhTFrF84ch%2FCteFF5Ilr%2FTHW7pb9pJCaOOuJ%2FMZIpXy2w9CtOXxbO8%2BkG4kHHDarz8M9w%3D%3D&amp;amp;X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Date=20220412T121324Z&amp;amp;X-Amz-SignedHeaders=host&amp;amp;X-Amz-Expires=600&amp;amp;X-Amz-Credential=ASIA25DCYHY3S4VTGYGI%2F20220412%2Fus-east-1%2Fs3%2Faws4_request&amp;amp;X-Amz-Signature=d84c5f4e44cf6473e0a924f3a5fd57aea32c00b17480af1551a869e41693b030"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"CodeSha256"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"f9IchJrdt01ftKIlcSZ25z6ZRbf780hO8xVYCd6Uxhs="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"CodeSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8748397&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"LayerArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:lambda:us-east-1:400803493251:layer:sharp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"LayerVersionArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:lambda:us-east-1:400803493251:layer:sharp:1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sharp dependency for image transformation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CreatedDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-04-12T12:13:27.990+0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CompatibleRuntimes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"nodejs14.x"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5 - Create Lambda function
&lt;/h2&gt;

&lt;p&gt;Now let’s create a Lambda function that will use the &lt;code&gt;sharp&lt;/code&gt; Lambda Layer. As discussed earlier, this Lambda function will be invoked when an object is created in the source bucket. Then it will create the respective thumbnail image and store it in the target bucket. The code example below assumes that you are following the S3 bucket name convention that is mentioned in Step-1.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5.1 Create the function code
&lt;/h3&gt;

&lt;p&gt;Copy the following code example into a file named &lt;code&gt;index.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// dependencies&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sharp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sharp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// get reference to S3 client&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;S3&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Read options from the event parameter.&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reading options from event:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;srcBucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Object key may have spaces or unicode non-ASCII characters.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;srcKey&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;decodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\+&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dstBucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;srcBucket&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-resized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dstKey&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;resized-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;srcKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Infer the image type from the file suffix.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typeMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;srcKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.([^&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;typeMatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Could not determine the image type.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Check that the image type is supported&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;typeMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageType&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;imageType&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unsupported image type: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;imageType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Download the image from the S3 source bucket.&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;srcBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;srcKey&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;origimage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// set thumbnail width. Resize will set the height automatically to maintain aspect ratio.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Use the sharp module to resize the image and save in a buffer.&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sharp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;origimage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Upload the thumbnail image to the destination bucket&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;destparams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dstBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dstKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;putResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;putObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destparams&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Successfully resized &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;srcBucket&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;srcKey&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; and uploaded to &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dstBucket&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dstKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5.2 Create the deployment package
&lt;/h3&gt;

&lt;p&gt;The deployment package is a &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html#gettingstarted-package-zip"&gt;.zip file archive&lt;/a&gt; containing your Lambda function code and its dependencies.&lt;/p&gt;

&lt;p&gt;1.) Open a command-line terminal or shell in a Linux environment.&lt;br&gt;
2.) Save the function code as &lt;code&gt;index.js&lt;/code&gt; in a directory named &lt;code&gt;lambda-s3&lt;/code&gt;.&lt;br&gt;
After this step, you have the following directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lambda-s3
|- index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3.) Create a deployment package with the function code and its dependencies. Set the -r (recursive) option for the zip command to compress the subfolders.&lt;br&gt;
Run this command from the &lt;code&gt;lambda-s3&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zip &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;.zip &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5.3 Create a Lambda function
&lt;/h3&gt;

&lt;p&gt;We will use the AWS CLI command (&lt;code&gt;aws lambda create-function&lt;/code&gt;) to create the Lambda function.&lt;/p&gt;

&lt;p&gt;Please replace the role parameter &lt;code&gt;123456789012&lt;/code&gt;with your &lt;a href="https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html"&gt;AWS account ID&lt;/a&gt; and layers ARN with the one we got in Step 4 (&lt;code&gt;LayerVersionArn&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda create-function &lt;span class="nt"&gt;--function-name&lt;/span&gt; CreateThumbnail &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--zip-file&lt;/span&gt; fileb://function.zip &lt;span class="nt"&gt;--handler&lt;/span&gt; index.handler &lt;span class="nt"&gt;--runtime&lt;/span&gt; nodejs14.x &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--timeout&lt;/span&gt; 30 &lt;span class="nt"&gt;--memory-size&lt;/span&gt; 1024 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--role&lt;/span&gt; arn:aws:iam::123456789012:role/lambda-s3-role &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--layers&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:lambda:us-east-1:400803493251:layer:sharp:1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the successful execution of the above command, you will see an output similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"FunctionName"&lt;/span&gt;: &lt;span class="s2"&gt;"CreateThumbnail"&lt;/span&gt;,
    &lt;span class="s2"&gt;"FunctionArn"&lt;/span&gt;: &lt;span class="s2"&gt;"arn:aws:lambda:us-east-1:400803493251:function:CreateThumbnail"&lt;/span&gt;,
    &lt;span class="s2"&gt;"Runtime"&lt;/span&gt;: &lt;span class="s2"&gt;"nodejs14.x"&lt;/span&gt;,
    &lt;span class="s2"&gt;"Role"&lt;/span&gt;: &lt;span class="s2"&gt;"arn:aws:iam::400803493251:role/lambda-s3-role"&lt;/span&gt;,
    &lt;span class="s2"&gt;"Handler"&lt;/span&gt;: &lt;span class="s2"&gt;"index.handler"&lt;/span&gt;,
    &lt;span class="s2"&gt;"CodeSize"&lt;/span&gt;: 1061,
    &lt;span class="s2"&gt;"Description"&lt;/span&gt;: &lt;span class="s2"&gt;""&lt;/span&gt;,
    &lt;span class="s2"&gt;"Timeout"&lt;/span&gt;: 30,
    &lt;span class="s2"&gt;"MemorySize"&lt;/span&gt;: 1024,
    &lt;span class="s2"&gt;"LastModified"&lt;/span&gt;: &lt;span class="s2"&gt;"2022-04-12T12:22:02.432+0000"&lt;/span&gt;,
    &lt;span class="s2"&gt;"CodeSha256"&lt;/span&gt;: &lt;span class="s2"&gt;"y0QVpF6+WN3wH1Zp+sbpbYlQEeAdkBuSf7p5aJV52Sc="&lt;/span&gt;,
    &lt;span class="s2"&gt;"Version"&lt;/span&gt;: &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LATEST&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;,
    &lt;span class="s2"&gt;"TracingConfig"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Mode"&lt;/span&gt;: &lt;span class="s2"&gt;"PassThrough"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;,
    &lt;span class="s2"&gt;"RevisionId"&lt;/span&gt;: &lt;span class="s2"&gt;"64dc7cab-9adf-4472-b20b-e15237209939"&lt;/span&gt;,
    &lt;span class="s2"&gt;"Layers"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="s2"&gt;"Arn"&lt;/span&gt;: &lt;span class="s2"&gt;"arn:aws:lambda:us-east-1:400803493251:layer:sharp:4"&lt;/span&gt;,
            &lt;span class="s2"&gt;"CodeSize"&lt;/span&gt;: 8748397
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;,
    &lt;span class="s2"&gt;"State"&lt;/span&gt;: &lt;span class="s2"&gt;"Pending"&lt;/span&gt;,
    &lt;span class="s2"&gt;"StateReason"&lt;/span&gt;: &lt;span class="s2"&gt;"The function is being created."&lt;/span&gt;,
    &lt;span class="s2"&gt;"StateReasonCode"&lt;/span&gt;: &lt;span class="s2"&gt;"Creating"&lt;/span&gt;,
    &lt;span class="s2"&gt;"PackageType"&lt;/span&gt;: &lt;span class="s2"&gt;"Zip"&lt;/span&gt;,
    &lt;span class="s2"&gt;"Architectures"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;"x86_64"&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;,
    &lt;span class="s2"&gt;"EphemeralStorage"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Size"&lt;/span&gt;: 512
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6 - Configure Amazon S3 Trigger
&lt;/h2&gt;

&lt;p&gt;So far we have created all the building blocks. Now let's add the final piece where we will configure the Amazon S3 Trigger to invoke the Lambda function.&lt;br&gt;
When a file is uploaded to S3, it should trigger the Lambda function that will resize, create a thumbnail, and upload it to the target S3 bucket.&lt;/p&gt;

&lt;h3&gt;
  
  
  To create an Amazon S3 Trigger
&lt;/h3&gt;

&lt;p&gt;1.) Open the &lt;a href="https://console.aws.amazon.com/lambda/home"&gt;Lambda page&lt;/a&gt; in the AWS console.&lt;br&gt;
2.) Open the &lt;code&gt;CreateThumbnail&lt;/code&gt; function.&lt;br&gt;
3.) Choose &lt;strong&gt;Add trigger&lt;/strong&gt; under the Function overview section&lt;br&gt;
4.) Create a trigger with the following properties:&lt;br&gt;
    - &lt;strong&gt;Select a trigger&lt;/strong&gt; – S3&lt;br&gt;
    - &lt;strong&gt;Bucket&lt;/strong&gt; - mybucket (your source bucket name)&lt;br&gt;
    - &lt;strong&gt;Event type&lt;/strong&gt; – &lt;strong&gt;PUT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JzCv5rt---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jafkp7utpz5jl4uj3ru4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JzCv5rt---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jafkp7utpz5jl4uj3ru4.png" alt="S3 Trigger Form" width="748" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7 - All set, let’s test it!
&lt;/h2&gt;

&lt;p&gt;Nice, we are all set with our Lambda function, which uses the sharp Layer and creates thumbnail images. Please upload an image (&lt;code&gt;jpg&lt;/code&gt; or &lt;code&gt;png&lt;/code&gt;) to the source S3 bucket. Once the upload is complete, you should be able to see the thumbnail version of the image in the target S3 bucket.&lt;/p&gt;

&lt;p&gt;Lambda Layer is a very efficient and convenient way to package libraries and other dependencies that you can use with your Lambda functions. It offers great benefits in reducing the deployment archives size and faster deployment. layers enable code sharing and separation of responsibilities to create maintainable Lambda functions.&lt;/p&gt;

&lt;p&gt;In case you want to explore and learn more about best coding practices and code examples related to Lambda, you can check out the &lt;a href="https://github.com/webiny/webiny-js/"&gt;Webiny code repository&lt;/a&gt;. Webiny is an open-source enterprise-grade serverless CMS.&lt;/p&gt;

&lt;p&gt;If you have any questions related to this tutorial or have any feedback, please feel free to ping us on the &lt;a href="https://webiny.com/slack/"&gt;Community Slack&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;As this tutorial aims to explain and demonstrate the use of Lambda Layer, we didn't reinvent the wheel and write a new Lambda function to create thumbnail images. The Lambda function code used in this article to create thumbnail images is taken from this &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/with-s3-tutorial.html"&gt;official AWS Lambda tutorial&lt;/a&gt;. Huge thanks to the authors of this great tutorial on the Lambda function. 🙏🏻&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
      <category>lambda</category>
      <category>layer</category>
    </item>
    <item>
      <title>Learn About Infrastructure as Code in 5 Minutes and Why You Should Use It</title>
      <dc:creator>Swapnil M Mane</dc:creator>
      <pubDate>Fri, 21 Jan 2022 09:15:06 +0000</pubDate>
      <link>https://forem.com/webiny/learn-about-infrastructure-as-code-in-5-minutes-and-why-you-should-use-it-4maj</link>
      <guid>https://forem.com/webiny/learn-about-infrastructure-as-code-in-5-minutes-and-why-you-should-use-it-4maj</guid>
      <description>&lt;p&gt;In the past, IT infrastructure management was challenging. Hardware and software had to be managed and configured manually. Recently, a tool, that allows you to simplify and automate these actions, has appeared. This tool is called infrastructure as code (IaC).&lt;/p&gt;

&lt;p&gt;In this article, we will discuss what infrastructure as code is, the best providers that allow you to implement IaC, IaC best practices, examples, and possible challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure as code declaration
&lt;/h2&gt;

&lt;p&gt;Infrastructure as Code (IaC) is the process of managing and configuring an infrastructure using configuration files, rather than manually editing configurations on servers or using interactive configuration tools. The IaC model creates the same environment every time it is applied. IaC is used in infrastructure as a service (IaaS), but they should not be confused. The main idea of IaC is to describe the infrastructure using code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it is needed
&lt;/h2&gt;

&lt;p&gt;Without IaC, teams must maintain customization of individual deployment environments. Over time, this leads to each environment having a unique configuration that cannot be reproduced automatically, which in turn leads to problems during deployment. In such a case, infrastructure administration and maintenance involve manual processes that are difficult to track and which can lead to errors. IaC allows you to always set the same configuration for the target environment, regardless of the initial state of the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The best IaC providers
&lt;/h2&gt;

&lt;p&gt;Let’s take a look at the most popular IaC providers and the main features they provide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Amazon AWS Cloudformation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/cloudformation/"&gt;AWS CloudFormation&lt;/a&gt; is a built-in IaC tool in the AWS Cloud Platform that provides the ability to provision and manage a set of multiple related AWS and third-party resources. CloudFormation lets you manage your resource scaling, automate resource management by integrating CloudFormation with other required AWS resources, and create your own resource providers to provide and manage third-party application resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Azure Resource Manager
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://azure.microsoft.com/features/resource-manager/"&gt;Azure Resource Manager&lt;/a&gt; is an IaC tool for deploying and managing Azure resources. It allows you to deploy, maintain, and track resources as a collective action rather than separately. It incorporates role-based access control into the resource control mechanism to enable users to enforce access control over all resources in a resource category.&lt;/p&gt;

&lt;h3&gt;
  
  
  Google Cloud Deployment Manager
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://cloud.google.com/deployment-manager/docs"&gt;Google Cloud Deployment Manager&lt;/a&gt; is an infrastructure deployment service designed to automate the creation, configuration, provision, and management of assets on the Google Cloud Platform. It allows you to easily create a collection of Google cloud assets and then manage them as a whole. Google Cloud Deployment Manager enables multiple resources to be deployed concurrently, controls the order in which resources are created, and creates resource definition dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terraform
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.terraform.io/"&gt;HashiCorp Terraform&lt;/a&gt; is the most popular open-source infrastructure automation tool. terraform allows you to easily plan and build IaC for multiple infrastructure providers with a single workflow. You can easily provision different environments using the same configuration and manage the complete lifecycle of the infrastructure you want; thereby reducing human error and increasing the automation of infrastructure provision and management.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS CDK
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://aws.amazon.com/cdk/"&gt;AWS CDK&lt;/a&gt; is a software development platform for defining cloud infrastructure in code and exposing it using AWS CloudFormation. It allows you to define the framework and application stack in programming languages such as Python, Java, Typescript, .NET, and JavaScript, and deploys a full-featured application stack directly from a supported IDE.&lt;/p&gt;

&lt;p&gt;AWS CDK allows you to automatically create a CloudFormation template based on your source code and deploy this template to your AWS account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pulumi
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.pulumi.com/"&gt;Pulumi&lt;/a&gt; is an open-source multilingual development platform that lets you manage your cloud infrastructure with code. It provides any cloud deployment functionality, cloud management. Pulumi offers the freedom to use any supported programming language you like. With Pulumi, you can view all existing environments and the changes you make to them. In addition, you can easily customize their configurations to protect your data.&lt;/p&gt;

&lt;h2&gt;
  
  
  IaC examples
&lt;/h2&gt;

&lt;p&gt;Let’s look at a simple scenario for provisioning an AWS EC2 instance. In the following example, we can see how Terraform code is used for this requirement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hashicorp/aws&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;~&amp;gt; 3.27&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;access_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws_access_key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;secret_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws_secret_key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-west-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws_instance&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;web_server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt;                    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ami-0123456&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;t3.small&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;subnet_id&lt;/span&gt;              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;subnet-a000111x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;vpc_security_group_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sg-dfdd00011&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;key_name&lt;/span&gt;               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;web_server_test_key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Web_Server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  IaC best practices
&lt;/h2&gt;

&lt;p&gt;Some of the best IaC practices to consider when developing it are listed below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version control
&lt;/h3&gt;

&lt;p&gt;Configuration files should be versioned so that you can easily track, manage, and recover any potential changes. Version control is also very helpful in diagnosing problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Document as little as possible
&lt;/h3&gt;

&lt;p&gt;When using IaC, the code is the infrastructure documentation and will always be up-to-date, so your employees don’t need to write a lot of additional instructions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modularity and microservices
&lt;/h3&gt;

&lt;p&gt;IaC can be used to develop, manage and maintain applications as many deployable modules. It also allows you to split your infrastructure into multiple modular components and then use automation to combine them in the most appropriate way.&lt;/p&gt;

&lt;h3&gt;
  
  
  IaC Compliance Regulation
&lt;/h3&gt;

&lt;p&gt;Errors in IaC files can be a serious problem if they are not detected prior to deploying IaC definitions. Therefore, it is recommended to automatically and continuously scan IaC files, ensuring that verification occurs whenever an IaC definition is created or updated. You can do it using such tools as &lt;a href="https://www.checkov.io/"&gt;Checkov&lt;/a&gt;, &lt;a href="https://github.com/terraform-linters/tflint"&gt;TFLint&lt;/a&gt;, &lt;a href="https://www.accurics.com/products/accurics/"&gt;Accurics&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  IaC challenges
&lt;/h2&gt;

&lt;p&gt;While there is a list of IaC advantages, there are certain issues with this model that need to be understood and solved before the IaC implementation process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shift of configuration
&lt;/h3&gt;

&lt;p&gt;In the long run, a configuration shift can occur, no matter how consistently or often you configure your servers. Therefore, every time you need to change your infrastructure, you must ensure that it is done in accordance with a predefined maintenance workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Potential duplication of errors
&lt;/h3&gt;

&lt;p&gt;In the process of implementing IaC, there are certain processes that must be done manually. One of these processes is writing the code that generates your IaC architecture, during which there is always the possibility of error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Need for new skills
&lt;/h3&gt;

&lt;p&gt;The IaC model requires a high level of technical expertise, so teams must continually invest in people and skills. For some teams, this may be too costly.&lt;/p&gt;

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

&lt;p&gt;IaC fully frees developers and other professionals from manual, error-prone tasks. In addition, it lowers costs and increases efficiency throughout the entire software development lifecycle.&lt;br&gt;
If you have questions or comments, please reach out via &lt;a href="https://twitter.com/paveldenisjuk"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.webiny.com/slack?utm_source=Webiny-blog&amp;amp;utm_medium=blog-post&amp;amp;utm_campaign=Regular-content&amp;amp;utm_content=what-is-infrastructure-as-code&amp;amp;utm_term=W00750"&gt;Webiny Community Slack&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introducing the new Object field 🚀</title>
      <dc:creator>Swapnil M Mane</dc:creator>
      <pubDate>Thu, 29 Jul 2021 11:20:41 +0000</pubDate>
      <link>https://forem.com/webiny/introducing-the-new-object-field-4ba</link>
      <guid>https://forem.com/webiny/introducing-the-new-object-field-4ba</guid>
      <description>&lt;p&gt;⚡️Seamlessly create nested and repeatable data structures with the new Object field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hrL-SjCV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/673772f4832f06e7ba3fd770d3fde4e5/c1b63/modelObjectField.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hrL-SjCV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/673772f4832f06e7ba3fd770d3fde4e5/c1b63/modelObjectField.png" alt="Headless CMS - Object Field"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the latest &lt;a href="https://www.webiny.com/docs/changelog/5.11.0/?utm_source=Webiny-blog&amp;amp;utm_medium=blog-post&amp;amp;utm_campaign=Regular-content&amp;amp;utm_content=introducing-new-object-field&amp;amp;utm_term=W00691"&gt;Webiny 5.11.0&lt;/a&gt; release, we are glad to introduce the new Object field in Headless CMS.&lt;br&gt;&lt;br&gt;
The nested and repeatable data structures was one of the hot topic discussed in the Webiny community. With the new Object field now, you can create complex data structures with ease. Huge thanks to our community members for their suggestions and contributions.&lt;/p&gt;

&lt;p&gt;Let's quickly dive into the highlighting capabilities of the Object field.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build nested data structures
&lt;/h3&gt;

&lt;p&gt;The new Object field allows you to build nested data structures. You can create an object and add various existing fields (&lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;richText&lt;/code&gt; field, etc.) to it. Along with this, you can also nest objects within other objects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9tQOl3S9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/fa36d25b44d74d7f09f980246cc8234c/58213/addressModel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9tQOl3S9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/fa36d25b44d74d7f09f980246cc8234c/58213/addressModel.png" alt="Address Model"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Repeatable structure
&lt;/h3&gt;

&lt;p&gt;The icing on the cake is, the data structure created with Object fields can be repeatable (like an array of nested objects).&lt;br&gt;&lt;br&gt;
The &lt;code&gt;Use as a repeatable object&lt;/code&gt; property allows creating the repeatable object. E.g. setting the 'Use as a repeatable object' property to true on the Equipment model will make it multi-valued.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pB7osym1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/223aeb206c3e3fa75474ff925a75499a/c1b63/useAsRepeatableObject.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pB7osym1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/223aeb206c3e3fa75474ff925a75499a/c1b63/useAsRepeatableObject.png" alt="Repeatable Object"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below is the model view for the multi-valued Equipment field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lsmravAK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/717cb376429ef612a9fe750ec1e5a82a/1cfc2/multiValuedModel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lsmravAK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/717cb376429ef612a9fe750ec1e5a82a/1cfc2/multiValuedModel.png" alt="Multi Value Model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the preview of the model will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EVEIlN7t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/bfbd1e4afdc9744cd44b93e1b1dbd3d8/e35ec/multiValuedModelPreview.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EVEIlN7t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/bfbd1e4afdc9744cd44b93e1b1dbd3d8/e35ec/multiValuedModelPreview.png" alt="Multi Value Model Preview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL Schema auto-complete support
&lt;/h3&gt;

&lt;p&gt;Object field respects all the rules and behaviors of all the other existing fields (&lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;richText&lt;/code&gt; field, etc.). You also get a full GraphQL Schema auto-complete on your nested fields.&lt;/p&gt;

&lt;p&gt;Alright, here is the &lt;a href="https://www.webiny.com/6d76a5f7c93600ce9ec7043ee7016dca/objectFieldDemo.gif"&gt;demo in action&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Try the new &lt;a href="https://www.webiny.com/serverless-cms?utm_source=Webiny-blog&amp;amp;utm_medium=blog-post&amp;amp;utm_campaign=Regular-content&amp;amp;utm_content=introducing-new-object-field&amp;amp;utm_term=W00693z"&gt;Headless CMS - Object field&lt;/a&gt; and please &lt;a href="https://www.webiny.com/slack/?utm_source=Webiny-blog&amp;amp;utm_medium=blog-post&amp;amp;utm_campaign=Regular-content&amp;amp;utm_content=introducing-new-object-field&amp;amp;utm_term=W00692"&gt;let us know&lt;/a&gt; your valuable feedback!&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>javascript</category>
      <category>cms</category>
      <category>aws</category>
    </item>
    <item>
      <title>5 Things to Avoid When Writing Cypress Tests</title>
      <dc:creator>Swapnil M Mane</dc:creator>
      <pubDate>Mon, 26 Jul 2021 09:15:05 +0000</pubDate>
      <link>https://forem.com/webiny/5-things-to-avoid-when-writing-cypress-tests-564e</link>
      <guid>https://forem.com/webiny/5-things-to-avoid-when-writing-cypress-tests-564e</guid>
      <description>&lt;p&gt;When it comes to testing an application, End-to-End (E2E) testing provides the most confidence and the most bang for the buck.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bv3JQTFB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/2a238110718f1be2fe5b43b5fc757b4e/8f77f/pyramid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bv3JQTFB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.webiny.com/static/2a238110718f1be2fe5b43b5fc757b4e/8f77f/pyramid.png" alt="Testing Pyramid"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the contrary, there is no doubt that End-to-End testing is hard, time-consuming, and comes with a bag of issues to solve. But, only if you're using the wrong tool for the job.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enter &lt;a href="https://www.cypress.io"&gt;Cypress&lt;/a&gt;: Fast, easy, and reliable testing for anything that runs in a browser&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Cypress helps in solving most of the pain points of End-to-End testing and makes it fun to write tests.&lt;br&gt;
But, there are certain mistakes to be avoided so that you can get the full benefit of working with Cypress.&lt;/p&gt;

&lt;p&gt;In this blog post, we'll cover 5 such common mistakes, which should be avoided when writing Cypress tests.&lt;br&gt;
So, without further ado, let's begin!&lt;/p&gt;
&lt;h2&gt;
  
  
  Use &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;class&lt;/code&gt; For Selecting Element
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;class&lt;/code&gt; for selecting element is problematic because they are primarily for behavior and styling purposes, due to which they are subject to change frequently.&lt;br&gt;
Doing so result in brittle tests which, you probably don't want.&lt;/p&gt;

&lt;p&gt;Instead, you should always try to use &lt;code&gt;data-cy&lt;/code&gt; or &lt;code&gt;data-test-id&lt;/code&gt;.&lt;br&gt;
Why? Because they are specifically for testing purposes, which makes them decoupled to the behavior or styling, hence more reliable.&lt;/p&gt;

&lt;p&gt;For example, let's suppose we have an &lt;code&gt;input&lt;/code&gt; element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
  &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input-box"&lt;/span&gt;
  &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;
  &lt;span class="na"&gt;data-testid=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of using &lt;code&gt;id&lt;/code&gt; or &lt;code&gt;class&lt;/code&gt; to target this element for test, use &lt;code&gt;data-testid&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Don't ❌&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.input-box&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Do ☑️&lt;/span&gt;
&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-testid=name]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What about using text for selecting element?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes it is necessary to use text such as button label to make an assertion or action.&lt;br&gt;
Although, it's perfectly fine, keep in mind that, your test will fail if the text changes, which is what you might want if the text is critical for the application.&lt;/p&gt;
&lt;h2&gt;
  
  
  Treating Cypress Commands as Promise
&lt;/h2&gt;

&lt;p&gt;Cypress tests are composed of Cypress commands, for example, &lt;code&gt;cy.get&lt;/code&gt; and &lt;code&gt;cy.visit&lt;/code&gt;.&lt;br&gt;
Cypress commands are like &lt;em&gt;Promise&lt;/em&gt;, but they are not real &lt;em&gt;Promise&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What that means is, we can't use syntax like &lt;code&gt;async-await&lt;/code&gt; while working with them. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// This won't work&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-testid=element]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Do something with element&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to do something after a command has been completed, you can do so with the help of the &lt;code&gt;cy.then&lt;/code&gt; command.&lt;br&gt;
It will guarantee that only after the previous command finishes, the next will run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// This works&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-testid=element]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$el&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Do something with $el&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note when using a clause like &lt;code&gt;Promise.all&lt;/code&gt; with Cypress command, it might not work as you expect because Cypress commands are like &lt;em&gt;Promise&lt;/em&gt;, but not real &lt;em&gt;Promise&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Arbitrary Waits in Cypress Tests
&lt;/h2&gt;

&lt;p&gt;When writing the Cypress test we want to mimic the behavior of a real user in real-world scenarios.&lt;br&gt;
Real-world applications are asynchronous and slow due to things like network latency and device limitations.&lt;/p&gt;

&lt;p&gt;When writing tests for such applications we are tempted to use arbitrary values in the &lt;code&gt;cy.wait&lt;/code&gt; command.&lt;br&gt;
The problem with this approach is that, while it works fine in development, it is not guaranteed. Why? Because the underlying system depends upon things like network requests which are asynchronous and nearly impossible to predict.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Might work (sometimes) 🤷&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-testid=element]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;performSomeAsyncAction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Wait for 1000 ms&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Do something else after the action is completed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, we should wait for visual elements, for example, completion of loading. Not only does it mimic the real-world use case more closely, but it also gives more reliable results.&lt;br&gt;
Think about it, a user using your application mostly likely wait for a visual clue like loading to determine the completion of an action rather than arbitrary time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// The right way ☑️&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-testid=element]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;performSomeAsyncAction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Wait for loading to finish&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-testid=loader]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;not.be.visible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Now that we know previous action has been completed; move ahead&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cypress commands, for example, &lt;code&gt;cy.get&lt;/code&gt; wait for the element before making the assertion, of course for a predefined &lt;strong&gt;timeout&lt;/strong&gt; value which you can &lt;a href="https://docs.cypress.io/guides/references/configuration#Timeouts"&gt;modify&lt;/a&gt;.&lt;br&gt;
The cool thing about &lt;strong&gt;timeout&lt;/strong&gt; is that they will only wait until the condition is met rather than waiting for the complete duration like the &lt;code&gt;cy.wait&lt;/code&gt; command.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using Different Domains within a Cypress Test
&lt;/h2&gt;

&lt;p&gt;One limitation of Cypress is that it doesn't allow using more than one domain name in a single test.&lt;/p&gt;

&lt;p&gt;If you try using more than one domain in a single test block &lt;code&gt;it(...)&lt;/code&gt; or &lt;code&gt;test(...)&lt;/code&gt;, Cypress will throw a security warning.&lt;br&gt;
This is the way Cypress has been &lt;a href="https://docs.cypress.io/guides/guides/web-security#Same-superdomain-per-test"&gt;built&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With that being said, sometimes there is a requirement to visit more than one domain in a single test. We can do so by splitting our test logic into multiple test blocks within a single test file. You can think of it as a multi-step test, for example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Test Page Builder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Step 1: Visit Admin app and do something&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Step 2: Visit Website app and assert something&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use a similar approach at Webiny for testing the &lt;a href="https://www.webiny.com/serverless-app/page-builder/?utm_source=Dev-to&amp;amp;utm_medium=blog-post&amp;amp;utm_campaign=Regular-content&amp;amp;utm_content=5-things-to-avoid-cypress-tests&amp;amp;utm_term=W00685"&gt;Page Builder application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Few things to keep in mind when writing tests in such a manner are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You cannot rely on persistent storage be it variable in test block or even local storage.&lt;br&gt;
Why? Because, when we issue a Cypress command with a domain other than the &lt;code&gt;baseURL&lt;/code&gt; defined in the &lt;a href="https://docs.cypress.io/guides/references/best-practices#Setting-a-global-baseUrl"&gt;configuration&lt;/a&gt;, Cypress performs a tear-down and does a full reload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blocks like &lt;code&gt;"before"&lt;/code&gt;, &lt;code&gt;"after"&lt;/code&gt; will be run for each such test block because of the same issue mentioned above.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Be mindful of these issues before adapting this approach and adjust the tests accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mixing Async and Sync Code
&lt;/h2&gt;

&lt;p&gt;Cypress commands are asynchronous, and they don't &lt;strong&gt;return&lt;/strong&gt; a value but &lt;strong&gt;yield&lt;/strong&gt; it.&lt;/p&gt;

&lt;p&gt;When we run Cypress it won't execute the commands immediately but read them serially and queue them.&lt;br&gt;
Only after it executes them one by one. So, if you write your tests mixing async and sync code, you will get the wrong results.&lt;br&gt;
For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;does not work as we expect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your-application&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Nothing happens yet&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-testid=submit]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Still nothing happening&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Nope, nothing&lt;/span&gt;

  &lt;span class="c1"&gt;// Something synchronous&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// evaluates immediately as []&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// It will never run because "el.length" will immediately evaluates as 0&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.another-selector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/*
    * This code block will always run because "el.length" is 0 when the code executes
    */&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.optional-selector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, use our good friend &lt;code&gt;cy.then&lt;/code&gt; command to run code after the command has been completed. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;does work as we expect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;your-application&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Nothing happens yet&lt;/span&gt;

  &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-testid=submit]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Still nothing happening&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Nope, nothing&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// placing this code inside the .then() ensures&lt;/span&gt;
      &lt;span class="c1"&gt;// it runs after the cypress commands 'execute'&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.new-el&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// evaluates after .then()&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.another-selector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.optional-selector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Cypress is a powerful tool for End-to-End testing, but sometimes we make few mistakes which makes the experience not fun.&lt;br&gt;
By avoiding the common mistakes we can make the journey of End-to-End testing smooth and fun.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What is Open Source?</title>
      <dc:creator>Swapnil M Mane</dc:creator>
      <pubDate>Mon, 26 Jul 2021 08:14:08 +0000</pubDate>
      <link>https://forem.com/swapnilmmane/what-is-open-source-1g2m</link>
      <guid>https://forem.com/swapnilmmane/what-is-open-source-1g2m</guid>
      <description>&lt;p&gt;&lt;a href="http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=Vo5FP0nwMtM&amp;lt;br&amp;gt;%0A"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y-RPJgeu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://img.youtube.com/vi/Vo5FP0nwMtM/0.jpg" alt="What is Open Source"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What is Open Source?&lt;/p&gt;

&lt;p&gt;Link to video chapter &lt;a href="https://youtu.be/Vo5FP0nwMtM"&gt;https://youtu.be/Vo5FP0nwMtM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open Source Software are those whose source code is publicly available to everyone. Anyone can freely use it, modify it and redistribute it.&lt;/p&gt;

&lt;p&gt;Let’s understand each term individually.&lt;/p&gt;

&lt;p&gt;Source Code&lt;/p&gt;

&lt;p&gt;A soul of any software is its code, most of user never see the source code, they use the software. &lt;/p&gt;

&lt;p&gt;But behind every software there is a code, which is compiled, transpiled or interpreted by the browser. &lt;/p&gt;

&lt;p&gt;So, in open source software, this source is available in public domain means anyone can see what is written in the code.&lt;/p&gt;

&lt;p&gt;Let’s take an example of Food Dish. so a food dish is the final thing you consume.&lt;/p&gt;

&lt;p&gt;But what is the core or soul of the dish? It is it’s recipe, the final Dish is outcome of recipe.&lt;/p&gt;

&lt;p&gt;So, it you make this recipe in public domain anybody can prepare that dish. Open Source is something like this.&lt;/p&gt;

&lt;p&gt;Now let’s see how an open source software can be freely used, Modified or Redistributed.&lt;/p&gt;

&lt;p&gt;[Use it]&lt;/p&gt;

&lt;p&gt;Since it is in publicly available anyone can see the code and use the software.&lt;/p&gt;

&lt;p&gt;[Modify it]&lt;/p&gt;

&lt;p&gt;Now if anybody want to make any change in software,&lt;/p&gt;

&lt;p&gt;For e.g. if you found any bug in the software, you can fix it and can contribute back to it or if you want to add a new feature you can do that as well.&lt;/p&gt;

&lt;p&gt;[Redistribute it]&lt;/p&gt;

&lt;p&gt;Once it modified, than the modified version of that software can be redistributed i.e. you have the ownership to redistribute it.&lt;/p&gt;

&lt;p&gt;So, this was concept of making source code available, so that anyone can freely use it, modify it and redistribute it.&lt;/p&gt;

&lt;p&gt;How the Open Source term was Coined?&lt;/p&gt;

&lt;p&gt;Link to video chapter &lt;a href="https://youtu.be/Vo5FP0nwMtM?t=135"&gt;https://youtu.be/Vo5FP0nwMtM?t=135&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Initially the free Software world was widely used but there were some problem with this word.&lt;/p&gt;

&lt;p&gt;Like when any business hears this term, free, they thought the Software will be cheap, unusable and worthless software  and they thought they couldn't make money out of it.&lt;/p&gt;

&lt;p&gt;And this terms was kind of confusing for newcomers, they often assume the free word is referring to the Price or Money, which was not the case.&lt;/p&gt;

&lt;p&gt;Actually the Free words was referring to the freedom at the philosophical level.   &lt;/p&gt;

&lt;p&gt;So, this was issue which needs to be address, On February 5, 1998, a group was assembled at VA Research and during this meeting Open Source termed was coined.&lt;/p&gt;

&lt;p&gt;The credit of inventing this term goes to Christine Peterson, we are thankful to her for this invaluable contribution.&lt;/p&gt;

&lt;p&gt;Whats makes a piece of software open source?&lt;/p&gt;

&lt;p&gt;Link to video chapter &lt;a href="https://youtu.be/Vo5FP0nwMtM?t=192"&gt;https://youtu.be/Vo5FP0nwMtM?t=192&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Just making source code available in public doesn’t makes it open source software.&lt;/p&gt;

&lt;p&gt;Author have to give rights to users to freely use, modify or redistribute it.&lt;/p&gt;

&lt;p&gt;So, how author can do it,&lt;/p&gt;

&lt;p&gt;The process is simple - By adding a License file in the code.&lt;/p&gt;

&lt;p&gt;In brief, License allow software to be freely used, modified, and shared.&lt;/p&gt;

&lt;p&gt;There are various open source license available, like Apache, MIT, GNU etc. &lt;/p&gt;

&lt;p&gt;Like if you have driving license, you are legally allowed to drive in the respective nation.&lt;/p&gt;

&lt;p&gt;Similarly if your code have open source License file, it will allow user to freely use it, modify it and share it.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
  </channel>
</rss>
