Creando a funcion en AWS lambda con Go


Introducción

En este artículo vamos a crear una función Lambda y una ruta en API Gateway, como hicimos con el framework serverless, pero utilizando únicamente las herramientas de AWS. Usaremos el mismo código generado para nuestra función del artículo anterior ¿Qué hace el framework serverless por mí?. Si querés saber cómo llegamos hasta acá, te recomiendo que lo leas primero. Este es un ejemplo básico de cómo empezar con Lambda sin ninguna herramienta adicional.


Veamos el código nuevamente

package main

import (
    "bytes"
    "context"
    "encoding/json"

    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
)

// Response es del tipo APIGatewayProxyResponse ya que estamos aprovechando
// la funcionalidad de AWS Lambda Proxy Request (comportamiento por defecto)
//
// https://serverless.com/framework/docs/providers/aws/events/apigateway/#lambda-proxy-integration
type Response events.APIGatewayProxyResponse

// Handler es nuestro manejador lambda invocado por la llamada a `lambda.Start`
func Handler(ctx context.Context) (Response, error) {
    var buf bytes.Buffer

    body, err := json.Marshal(map[string]interface{}{
        "message": "¡Go Serverless v1.0! Tu función se ejecutó correctamente.",
    })
    if err != nil {
        return Response{StatusCode: 404}, err
    }
    json.HTMLEscape(&buf, body)

    resp := Response{
        StatusCode:      200,
        IsBase64Encoded: false,
        Body:            buf.String(),
        Headers: map[string]string{
            "Content-Type":           "application/json",
            "X-MyCompany-Func-Reply": "hello-handler",
        },
    }

    return resp, nil
}

func main() {
    lambda.Start(Handler)
}

Con este código como punto de partida, ahora necesitamos compilar, empaquetar, subir y desplegar nuestra función:


Compilar

GOOS=linux go build main.go

Empaquetar

zip main.zip ./main
# OUTPUT:
#   adding: main (deflated 51%)

Crear el rol

Ve a IAM > Roles > Crear.
Luego selecciona Lambda, asigna un nombre y una descripción, y obtené el ARN de este rol. Con el framework serverless esto se hace automáticamente, así que no es necesario crear un nuevo rol cada vez.


Subir / Desplegar

aws lambda create-function \
  --region us-east-1 \
  --function-name helloworld \
  --memory 128 \
  --role arn:aws:iam::894527626897:role/testing-aws-go \
  --runtime go1.x \
  --zip-file fileb://main.zip \
  --handler main

# OUTPUT:
# {
#     "FunctionName": "helloworld",
#     "FunctionArn": "arn:aws:lambda:us-east-1:894527626897:function:helloworld",
#     "Runtime": "go1.x",
#     "Role": "arn:aws:iam::894527626897:role/testing-aws-go",
#     "Handler": "main",
#     "CodeSize": 4346283,
#     "Description": "",
#     "Timeout": 3,
#     "MemorySize": 128,
#     "LastModified": "2019-02-16T15:44:10.610+0000",
#     "CodeSha256": "02/PQBeQuCC8JS1TLjyU38oiUwiyQSmKJXjya25XpFA=",
#     "Version": "$LATEST",
#     "TracingConfig": {
#         "Mode": "PassThrough"
#     },
#     "RevisionId": "7c9030e5-4a26-4f7e-968d-3a4f65dfde21"
# }

Ten en cuenta que el nombre de tu función (function-name) debe coincidir con el nombre de tu manejador Lambda (Handler). Este rol podría ser inseguro si le das demasiados permisos, así que tratá de restringirlo lo más posible, como con cualquier rol y política.


Probar la función

aws lambda invoke --function-name helloworld --log-type Tail /dev/stdout
# OUTPUT:
# {"statusCode":200,"headers":{"Content-Type":"application/json","X-MyCompany-Func-Reply":"hello-handler"},"body":"{\"message\":\"Go Serverless v1.0! Your function executed successfully!\"}"}

Todo parece estar bien. Lo siguiente es comunicarnos con este código desde una fuente externa, así que vamos a ver cómo hacerlo con API Gateway. Además, los logs están codificados en base64, así que si querés ver el resultado del log, hacé lo siguiente.


Ver los logs

echo "U1RBUlQgUmVxdWVzdElkOiBmZTRmMWE4Zi1kYzAyLTQyYWQtYjBlYy0wMjA5YjY4MDY1YWQgVmVyc2lvbjogJExBVEVTVApFTkQgUmVxdWVzdElkOiBmZTRmMWE4Zi1kYzAyLTQyYWQtYjBlYy0wMjA5YjY4MDY1YWQKUkVQT1JUIFJlcXVlc3RJZDogZmU0ZjFhOGYtZGMwMi00MmFkLWIwZWMtMDIwOWI2ODA2NWFkCUR1cmF0aW9uOiAxMy4xOSBtcwlCaWxsZWQgRHVyYXRpb246IDEwMCBtcyAJTWVtb3J5IFNpemU6IDEyOCBNQglNYXggTWVtb3J5IFVzZWQ6IDQ1IE1CCQo=" | base64 -d
# OUTPUT:
# START RequestId: fe4f1a8f-dc02-42ad-b0ec-0209b68065ad Version: $LATEST
# END RequestId: fe4f1a8f-dc02-42ad-b0ec-0209b68065ad
# REPORT RequestId: fe4f1a8f-dc02-42ad-b0ec-0209b68065ad  Duration: 13.19 ms      Billed Duration: 100 ms         Memory Size: 128 MB     Max Memory Used: 45 MB

También deberías poder ver este mismo output en CloudWatch.


API Gateway

Para simplificar este paso, decidí usar la consola de AWS en lugar de la CLI. También acorta bastante el tamaño de este artículo.


Crear el endpoint en API Gateway

Solo tenés que ir a Lambda -> Funciones -> helloworld -> Add triggers -> API Gateway. Completá los campos como se muestra en la imagen, y cuando guardes este nuevo disparador, obtendrás el recurso que luego se podrá usar para probar la integración de API Gateway. img


El endpoint se verá así (hacé clic en API Gateway): image


Probar el API

curl -v https://r8efasfb26.execute-api.us-east-1.amazonaws.com/default/helloworld
# OUTPUT:
# *   Trying 54.236.123.239...
# * TCP_NODELAY set
# * Connected to r8efasfb26.execute-api.us-east-1.amazonaws.com (54.236.123.239) port 443 (#0)
# ...
# {"message":"¡Go Serverless v1.0! Tu función se ejecutó correctamente!"}

Si me lo preguntás, fue mucho esfuerzo manejar esto sin automatización. Tal vez AWS SAM o el framework serverless puedan hacer las cosas más fáciles y permitirte enfocarte en tu aplicación en lugar de en el boilerplate necesario para que funcione.


Limpiar

Siempre recordá limpiar y eliminar todo lo que creaste (para evitar sorpresas y ahorrar dinero). En este artículo, dejaré eso como un ejercicio para vos :)


Errata

Si encontrás algún error o tenés alguna sugerencia, por favor enviame un mensaje para que lo corrija.



No tienes cuenta? Regístrate aqui

Ya registrado? Iniciar sesión a tu cuenta ahora.

Iniciar session con GitHub
Iniciar sesion con Google
  • Comentarios

    Online: 0

Por favor inicie sesión para poder escribir comentarios.

by Gabriel Garrido