4

I'm trying to develop a lambda that has to work with S3 and dynamoDB. The thing is that because I am not familiar with the SDK of aws for go I will have lots of tests and tries. Each time I will change the code is another time I have to compile the project and upload it to aws. Is there any way to do it locally? pass some kind of configuration that lets me call the services of aws locally, from my computer? Thanks!

This has to do mostly with golang, other languages like python can run directly on the aws lambda function page, and node has cloud9 support.

4
  • 2
    Possible duplicate of How can I test AWS Lambda functions locally? Commented Dec 27, 2018 at 17:59
  • 1
    You're absolutely right; having to upload a function to test your code is insanity. There's a few, relatively complicated tools that AWS provides to facimilate the lambda runtime locally. aws.amazon.com/about-aws/whats-new/2017/08/… is one option. I usually try to get the code working locally without too much tooling for ease of development. Commented Dec 27, 2018 at 18:02
  • 2
    @Flimzy There is no duplication, this is a special case of golang being not supported by cloud9 (as apposed to node.js and python) and having an annoying running cycle which requires you to build and upload the file for each change. Commented Dec 27, 2018 at 18:39
  • @DanFarrell I have seen people recommend SAM. Thought maybe there are other options that I just could not find. Will check SAM for now, Hoping there will be something better. Commented Dec 27, 2018 at 18:39

3 Answers 3

4

You can use the lambci docker image(s) to execute your code locally using the same Lambda runtimes that are used on AWS.

https://github.com/lambci/docker-lambda

You can also run dynamo DB locally in another container as well

https://hub.docker.com/r/amazon/dynamodb-local/

To simulate credentials/roles that would be available on Lambda, just pass in your Api creds VIA environment variables. ( for s3 access )

Cheers -JH

Sign up to request clarification or add additional context in comments.

3 Comments

these are good suggestions, but I rather disagree with "just pass in your Api creds". Better to assume the role the lambda will be under, and pass those creds. Otherwise, you're postponing until a very inconvenient time (after development) the process of defining the required permissions. I prefer to create an empty role for lambda, assume it, and start adding permissions as I develop.
I see no problem with passing in API creds VIA environment vars to a docker container when developing locally (IE: creds for a user, or assume a role VIA STS and generate a session token). I know no other way to simulate a resource's access VIA an IAM Role locally. Perhaps you can enlighten me on how to do so, would be much appreciated.
I mean to distinguish between your creds as the AWS developer and the application's threads as the role lambda will run under. But there are other ways you can expose the creds, even to a lambda, that can be used. You can mount a config file into your docker container at the usual path. A config file can be configured to automatically assume a role ( as long as MFA isn't required or part of the assuming profile). Or, local metadata server is a not unheard-of option docs.aws.amazon.com/sdk-for-go/v1/developer-guide/…
2

I like the newish AWSLabs Go API Proxy for this: https://github.com/awslabs/aws-lambda-go-api-proxy

It allows you to write a standard HTTP server using your tools of choice (plain old go, Gin, Gorilla, etc), then run that server on Lambda. It has several benefits:

  • Removes almost all Lambda specific code/conventions from your codebase for more idiomatic go
  • Easily covert existing golang HTTP server to lambda execution mode
  • Support parallel execution modes. I use a ENV variable to switch between them in example below. I use straight HTTP for local dev, and Lambda for deployment.

Example app with 1 function

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"

    "github.com/aws/aws-lambda-go/lambda"
    "github.com/awslabs/aws-lambda-go-api-proxy/httpadapter"
)

// map of our functions, which can be handled as HTTP or Lambda
var functions = map[string]http.HandlerFunc{
    "ping": PingHandler,
}

func main() {
    for name, handler := range functions {
        path := fmt.Sprintf("/%s", name)
        http.HandleFunc(path, handler)
    }

    httpPort := os.Getenv("HTTP_PORT")
    if httpPort == "" {
        log.Println("Starting Lambda Handler")
        lambda.Start(httpadapter.New(http.DefaultServeMux).ProxyWithContext)
    } else {
        log.Printf("Starting HTTP server on port %s\n", httpPort)
        formattedPort := fmt.Sprintf(":%s", httpPort)
        log.Fatal(http.ListenAndServe(formattedPort, nil))
    }
}

// Sample Func
func PingHandler(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "pong")
}

Running as HTTP is easy: go build -out main && HTTP_PORT=7575 ./main. This is super fast, making it easy to rebuilt and test.

You can still build and run in a docker container to test Lambda mapping before deploying using the steps others have mentioned.

Comments

2

You can download locally the AWS lambda runtime environment as described in AWS documentation

mkdir -p ~/.aws-lambda-rie && curl -Lo ~/.aws-lambda-rie/aws-lambda-rie \
https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie \
&& chmod +x ~/.aws-lambda-rie/aws-lambda-rie               

To test the lambda function locally run you can then run on a terminal session:

~/.aws-lambda-rie/aws-lambda-rie go run main.go

This will start a server listening on port 8080. To actually trigger the lambda function, you can finally run on another terminal session:

curl -XPOST "http://localhost:8080/2015-03-31/functions/function/invocations" -d '{"Name": "World"}'

Last but not least, I'd suggest you to have a look at localstack. You can start a docker container that runs locally and will mock AWS S3 & DynamoDB APIs, so you can check your code for correctness still without having to deploy anything to AWS.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.