DEV Community

Cover image for Deploy lambda using serverless
aseem wangoo
aseem wangoo

Posted on

Deploy lambda using serverless

In case it helped :)
Pass Me A Coffee!!

We will cover briefly:

  1. Options for deploying lambda
  2. Setup serverless
  3. Create lambda (upload image to s3 bucket) using serverless
  4. Deploy lambda using serverless

Options for deploying lambda

As of writing this article, there are two ways of deploying lambdas onto AWS

Deploy lambda using serverless
Deploy lambda using serverless

The AWS Serverless Application Model (AWS SAM) is an open-source framework that you can use to build serverless applications on AWS

One of the key benefits of SAM is Local debugging and testing

It lets you locally build, test, and debug serverless applications that are defined by AWS SAM templates. which helps you catch issues upfront by providing parity with the actual Lambda execution environment

Develop, deploy, troubleshoot, and secure your serverless applications with radically less overhead and cost by using the Serverless Framework. The Serverless Framework consists of an open-source CLI.

Serverless allows us to focus on the code, while it takes care of the setting up policies, and provisioning of required infrastructure onto AWS

Setup serverless

To install serverless, follow here. Personally, I configured using the below

npm install -g serverless
Enter fullscreen mode Exit fullscreen mode
  • Once installed you can access it by typing sls on your terminal
  • We now have access to multiple templates by this command
sls create --help
Enter fullscreen mode Exit fullscreen mode

We will focus on the Go specific one, which is aws-go-dep Let's use this template to create a simple lambda. The final command for that is

sls create --template aws-go-dep --path upload-s3
Enter fullscreen mode Exit fullscreen mode

--template is used to specify the template name

--path (Optional) is used to specify the directory in which your code is to be placed

  • We should see a folder structure like this

Golang serverless folder structure
Golang serverless folder structure

  • By default, the aws-go-dep a template gives us two http (GET)based endpoints, which can be seen in the serverless.yml
functions:
  hello:
    handler: bin/hello
    events:
      - httpApi:
          path: /hello
          method: get
  world:
    handler: bin/world
    events:
      - httpApi:
          path: /world
          method: get
Enter fullscreen mode Exit fullscreen mode

The equivalent files correspond to hello/main.go and world/main.go 

  • In case you see errors, try to run the following commands
go mod init <SOME NAME HERE>
go mod tidy
Enter fullscreen mode Exit fullscreen mode

This will help in setting the go.mod which is required for any go program

Create lambda (upload image to s3 bucket) using serverless

We will modify our lambda to upload an image to an S3 bucket.

  • We delete the unnecessary endpoints from the serverless.yml and unwanted folders like hello/main.go and world/main.go 
  • Create a new folder called upload and inside it creates a file main.go 

Our final upload lambda structure
Our final upload lambda structure

  • We will define a request body struct that will accept filename and the body as input. (Note: the body would be the base64 encoder of an image)

For getting the base64 of any image, check here

type ImageRequestBody struct {
 FileName string `json:"filename"`
 Body     string `json:"body"`
}
Enter fullscreen mode Exit fullscreen mode

We will parse the body from the input and decode it using DecodeString which returns the bytes represented by the base64 string

decoded, err := base64.StdEncoding.DecodeString(bodyRequest.Body)
Enter fullscreen mode Exit fullscreen mode

All our image-related functions are inside img_utils.go. After decoding the image into bytes from the previous step, we now take those bytes and form a temporary file

func imageUpload(data []byte) {
  tmpFileName := fmt.Sprintf(`/tmp/%s`, bodyRequest.FileName)
  fileErr := ioutil.WriteFile(tmpFileName, []byte(data), 0644)

  // CALL THE UPLOAD FUNCTION
  UploadImage(tmpFileName)
}
Enter fullscreen mode Exit fullscreen mode

In the first line, we are specifying the file at a location tmp . This is an important step and as per AWS documentation

The Lambda execution environment provides a file system for your code to use at /tmp. This space has a fixed size of 512 MB. Each time a new execution environment is created, this area is deleted.

Next, we write the file with the bytes using WriteFile 

WriteFile writes data to a file named by filename. If the file does not exist, WriteFile creates it with permissions perm (before umask); otherwise WriteFile truncates it before writing, without changing permissions.

So now we have our temporary file created!

  • Now we will upload the file, onto the AWS S3 bucket. For that, we will be using the AWS GO SDK and in case you don’t have it installed follow this
go get github.com/aws/aws-sdk-go
Enter fullscreen mode Exit fullscreen mode

We will pass our file to the upload function

func uploadToS3Bucket(file io.Reader, fileName string) {
 bucketName := os.Getenv("bucket_name")
 region := "us-east-2"
 conf := aws.Config{Region: &region}
 sess, _ := session.NewSession(&conf)
 uploader := s3manager.NewUploader(sess)
 upParams := &s3manager.UploadInput{
   Bucket: &bucketName,
   Key:    &fileName,
   Body:   file,
 }
 result, err := uploader.Upload(upParams)
}
Enter fullscreen mode Exit fullscreen mode
  • We need to specify the region using aws.Config . In our case it was us-east-2.
  • We need to specify the region using aws.Config . In our case it was us-east-2.

session.Newsession returns a new Session created from SDK defaults, config files, environment, and user-provided config files.

aws-sdk-go gives us s3Manager which helps in uploading the file. It takes in

Bucket : Your AWS bucket name, in my case I get from serverless.yml environment variable

Key : Object key for which the PUT action was initiated. In our case, it's the filename.

Body : What is the body payload to send to S3. In our case, it's the file itself

  • Finally, using the above parameters, we call the Uploader.Upload 
  • We return the response from the main.go back to the caller

Deploy lambda using serverless

Till now we were creating our lambda, but now it's time to deploy it onto AWS.

  • Let’s revisit our serverless.yml and make some changes
functions:
  upload:
    handler: bin/upload
    events:
      - httpApi:
          path: /uploadImage
          method: post
Enter fullscreen mode Exit fullscreen mode

We add in the post endpoint uploadImage for our lambda

  • Next, since we are using the S3 bucket from inside lambda, we will add some IAMRoleStatements
custom:
  s3Bucket: test-bucket--aseem

iamRoleStatements:
    - Effect: Allow
      Action:
        - s3:*
      Resource: "arn:aws:s3:::${self:custom.s3Bucket}/*"
Enter fullscreen mode Exit fullscreen mode

This specifies the bucket name using s3Bucket and allows executing the operations on this bucket

  • Finally, for specifying the environment variables, we make use of
environment:
    bucket_name: test-bucket--aseem
Enter fullscreen mode Exit fullscreen mode

We will create a Makefile and put the following

deploy: clean build
 sls deploy --verbose
remove:
 sls remove
Enter fullscreen mode Exit fullscreen mode

This will help in easing the lambda deployment, by simply calling

make deploy
Enter fullscreen mode Exit fullscreen mode

If everything was successful, you should see something like this

Deploy lambda using serverless
Deploy lambda using serverless

For removing the lambda, we can call

make remove
Enter fullscreen mode Exit fullscreen mode

For testing the lambda, use the

curl -X POST -H "Content-Type: application/json" \
-d '{"filename": "xyz.png", "body": "BASE_64_ENCODING_OF_AN_IMAGE"}' \
<YOUR_LAMBDA_URL>
Enter fullscreen mode Exit fullscreen mode

Image uploaded to S3
Image uploaded to S3

Source code.

In case it helped :)
Pass Me A Coffee!!

Top comments (0)