holy-lambda

2022-02-16T17:59:08.430209Z

Hello 🙂 I am new to Lambda and holy-lambda and trying to setup a deps layer for my babashka backend. I added a file download-pods.clj , separate from my core.cljc :

(ns com.revivemedia.amc-utility.download-pods
  (:require
   [babashka.pods :as pods]))

(pods/load-pod 'org.babashka/aws "0.1.2")
(pods/load-pod 'org.babashka/buddy "0.0.1")
(pods/load-pod 'org.babashka/postgresql "0.1.0")
But I'm not sure about how to go about setting up the layer

2022-03-16T19:02:59.649029Z

Heya, this isn't a HL specific question but I wonder if you might have any advice about it. I am trying to deploy my lambdas to two separate stacks for testing and production. However when I run sam deploy --stack-name amc-test , it fails because the Lambas already exist by that name in my existing stack. How do you typically approach this problem?

Karol Wójcik 2022-03-16T19:13:27.995929Z

Reference the stack name in a function name via !Sub.

2022-03-16T19:15:47.963329Z

Like in my template.yml when I declare the functions?

Karol Wójcik 2022-03-16T20:34:38.434989Z

Yeah.

👍 1
2022-03-17T01:16:19.466629Z

Thanks so much 🙂 I got it to work!

2022-02-24T17:56:37.609589Z

Ah, I switched to clojure backend.

Karol Wójcik 2022-02-21T15:08:56.532839Z

Cc @nickstares0

Karol Wójcik 2022-02-16T18:20:02.925199Z

Do you mean a layer of dependencies?

2022-02-16T18:21:43.987189Z

Exactly

Karol Wójcik 2022-02-16T18:23:30.531619Z

1. Put the symbol/version pairs to bb.edn configuration in :pods keyword. 2. Run bb hl:babashka:sync to download the pods to a directory 3. Make a layer the same way as it's specified in documentation (babashka holy lambda tutorial), but point to .holy-lambda/pods 4. Link the layer with your function by a reference. 5. Verify if it works by using sam local invoke.

👍 1
Karol Wójcik 2022-02-16T18:24:36.797749Z

holy-lambda has it's own mechanism of downloading the pods, so the pods will never get redownloaded in Lambda environment.

Karol Wójcik 2022-02-16T18:26:11.516929Z

Also check if your dependencies are not bigger than 250mb, since otherwise you would have to pack the lambda in docker image.

2022-02-16T18:29:32.224809Z

Looks like I am good at 182mb 🙂

2022-02-16T18:30:51.891829Z

However I'm having trouble understanding step 3, in the babashka holy lambda tutorial, where does it show how to create a layer? I've already run through the tutorial before and deployed an example without pods but I don't understand the layer creation process

2022-02-16T18:39:37.719409Z

Are you saying to add another Resource in template.yml like so?

Resources:
  BabashkaDepsLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: BabashkaDepsLayer
      ContentUri: ./.holy-lambda/bb-clj-deps

  BabashkaPodsLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: BabashkaPodsLayer
      ContentUri: ./.holy-lambda/pods

2022-02-16T18:43:41.660179Z

and for step 4 do you mean this?

AmcUtilityFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: AmcUtilityFunction
      Handler: com.revivemedia.amc-utility.core.ExecuteWorkflow
      # For docker based deployments use:
      # PackageType: Image
      # and remove Runtime parameter
      CodeUri: src
      Events:
        HelloEvent:
          Type: HttpApi
          Properties:
            ApiId: !Ref ServerlessHttpApi
            Path: /
            Method: GET
      Layers:
        - arn:aws:lambda:us-east-1:430000000:layer:holy-lambda-babashka-runtime-amd64:3
        - !Ref BabashkaPodsLayer
        - !Ref BabashkaDepsLayer

2022-02-16T18:56:02.629169Z

sam local invoke builds the layers but I get

----- Error --------------------------------------------------------------------
Type:     java.lang.Exception
Message:  Could not find namespace: pod.babashka.aws.
Location: 19:1
I verified that the pods are in .holy-lambda/pods

Karol Wójcik 2022-02-16T19:03:48.206559Z

Looks good.

Karol Wójcik 2022-02-16T19:04:08.691199Z

How do you require the pod?

Karol Wójcik 2022-02-16T19:05:15.181619Z

This is the issue of how you do require the pod.

2022-02-16T19:07:45.109299Z

(require '[pod.babashka.aws :as aws]
         '[pod.babashka.aws.credentials :as credentials]
         '[pod.babashka.buddy.codecs :as codecs]
         '[pod.babashka.buddy.hash :as hash]
         '[pod.babashka.buddy.mac :as mac]
         '[pod.babashka.postgresql :as pg])

Karol Wójcik 2022-02-16T19:08:56.689679Z

Have you loaded the pod before the require?

2022-02-16T19:11:22.319529Z

Ah! I had that before but I took it out because I thought that was happening in the sync process. Added it back in and it's working now. Thank you so much!

2022-02-16T19:11:53.296239Z

If you think it would be helpful I will consider making a PR to the docs spelling this out so it is more obvious for someone with my experience level with Lambda layers

Karol Wójcik 2022-02-16T19:13:58.097169Z

Yes please. I really need PRs for documentation. If you willing to make the docs better please do. I’m migrating the docs to docosaurus since the formatting of the current solution is far from acceptable. I’m willing to create better, more complete docs, but still help is much appreciated.

👍 1
2022-02-17T01:52:37.700459Z

Strange, apparently I am exceeding the dependency size Resource handler returned message: "Layers consume more than the available size of 262144000 bytes Even though bb-clj-deps and pods are smaller than 250mb. Is it also including .babashka somehow?

2022-02-17T01:57:11.708329Z

better:

nick@Nicks-MacBook-Pro-2 .holy-lambda % du -hs $(ls -A)
 12K	.DS_Store
179M	.babashka
8.3M	bb-clj-deps
174M	pods

2022-02-17T02:04:52.146959Z

If I needed to, how would I pack the lambda as a docker image?

Karol Wójcik 2022-02-17T05:37:00.178679Z

There is also a layer that includes babashka as a binary.

Karol Wójcik 2022-02-17T05:37:51.302439Z

Wouldn't you want to try native runtime instead?

Karol Wójcik 2022-02-17T05:40:59.978569Z

You got three options: 1. Remove one pod from the layer, so it will get redownloaded during the execution. 2. Create a docker image, but this is not documented and I will have to guide you how to do this. 3. You can use native runtime instead

Karol Wójcik 2022-02-17T07:30:26.455879Z

> If I needed to, how would I pack the lambda as a docker image? 1. Create a Dockerfile 2. Set a workdir to /opt 3. Take a zip of babashka layer and copy the content to /opt directory 4. Change workdir to /var/task and copy all the content of dependencies and pods to this directory 5. After this you would have to plug the Dockerfile in template.yml config 6. Try to build the image via sam build 7. Deploy the function via sam deploy -g to ensure a image registry creation.

2022-02-22T18:07:32.785539Z

Hey just saw this. Not sure why notifications weren't working on my phone. I was OOO for the holiday weekend in USA. Thanks so much for building out that example! I can see that the env vars are there so let me dig into the permissions and see if I set them up properly

2022-02-22T18:09:14.683989Z

Behind the AWS private endpoint is a service called Amazon Marketing Cloud which is in private beta at the moment.

2022-02-22T18:40:24.350629Z

The problem is that babashka.curl/post is returning nil and I can't figure out why, maybe it's not an authorization issue but I don't know how I would determine that

Karol Wójcik 2022-02-22T19:36:56.231579Z

Is there a chance you can determine if actual network call is made?

2022-02-22T19:38:06.820329Z

How could I see if a network call is made?

Karol Wójcik 2022-02-22T19:39:25.788889Z

Have you checked if curl could be replace with this https://github.com/clj-commons/clj-http-lite/tree/master

2022-02-22T19:40:28.199989Z

Probably could, let me give it a shot

Karol Wójcik 2022-02-22T19:40:45.336789Z

First thing I would try is to make a HTTP call locally

Karol Wójcik 2022-02-22T19:40:55.188399Z

To this endpoint with the fake data

Karol Wójcik 2022-02-22T19:42:09.705799Z

I mean I expect it's not a fault of Lambda or HL. It's either issue with your code or in curl, so lets narrow the scope of the test.

2022-02-22T19:42:48.145099Z

Oh yeah, I'm able to make the call locally, just not working in production

2022-02-22T19:45:03.685999Z

Ah, I logged the credentials (probably bad practice) and then plugged them into my local setup and I got

"{\"Message\":\"User: arn:aws:sts::***:assumed-role/sam-app-AmcUtilityFunctionCljRole-1J5RNRMA9YX2O/AmcUtilityFunctionClj is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-1:********3042:ry8g3pqgz4/prod/POST/workflowExecutions\"}",
So looks like I need to set that authorization 👍

2022-02-22T19:45:40.028919Z

Annoying that I couldn't just get it to log that message in prod though. Maybe switching to clj-http-lite will make that easier

Karol Wójcik 2022-02-22T20:07:07.762589Z

Hard to tell. Maybe there is some kind of regression in Babashka curl in Amazon Linux. As far as I remember the Babashka curl is writing the headers file to temp. I dont remember whether it is or is not supported in Lambda environment. If I were you I would make a test with basic GET HTTP call to some known domain like Google with additional header to make sure this is not an internal issue in bb curl.

2022-02-23T01:10:33.384439Z

Wow, the problem was very silly on my end. I had a function called request which was being shadowed by [{:keys [event ctx] :as request}] in the scope of the lambda function

Karol Wójcik 2022-02-23T07:41:55.273839Z

Cool 🙂

2022-02-23T23:10:41.036539Z

For a second lambda fn, do you recommend another file in the same project or a new project? How does that work with the docker image build process?

Karol Wójcik 2022-02-24T06:16:27.598349Z

1. Question: are you using Babashka runtime in docker? 2. How you do set a handler for a lambda function?

Karol Wójcik 2022-02-24T06:21:36.025669Z

Anyway, if your functionality is similiar then just put another defn in your code and reference this defn in entrypoint macro. As a next step point to this new handler in deployment descriptor of a new Lambda. Basically you can override the CMD (that is in Dockerfile) in template.yml or AWS Console. No need to create a separate project.

👍 1
Karol Wójcik 2022-02-17T13:45:59.316759Z

Btw it might be easier to use native backend instead

2022-02-17T17:59:20.777579Z

Ok maybe I will give native backend a shot

Karol Wójcik 2022-02-17T19:24:38.363599Z

Cool I’m happy to help ;)

Karol Wójcik 2022-02-17T19:25:12.765569Z

The first time seems hard, but when you get used to the process you will be quite happy with the results ;)

Karol Wójcik 2022-02-17T19:26:20.084609Z

Which service are you planning to use with AWS cognitect api?

2022-02-17T19:41:33.728989Z

Thanks so much for offering to help! I think the first step is to build one of the native examples, maybe the sqs one

2022-02-17T19:42:33.445489Z

Right now I'm using STS (maybe not necessary since I may be able to get the session tokens I need from KMS within lambda?), S3 and SQS

Karol Wójcik 2022-02-17T19:50:19.212659Z

Fine. You therefore need to have 3 clients and at least one stub invoke of each client to correctly gather the resources of AWS Cognitect API during bb hl:native:conf call

👍 1
2022-02-17T20:16:43.087859Z

not sure why this is happening:

nick@Nicks-MacBook-Pro-2 sqs.example % bb hl:doctor
----- Error --------------------------------------------------------------------
Type:     java.lang.Exception
Message:  File does not exist: hl:doctor

2022-02-17T20:19:54.615829Z

This appears to work but then gives the same error:

nick@Nicks-MacBook-Pro-2 sqs.example % bb hl:compile
Checking out:  at 2098fc6860948bc854a4f9bc55a0dc6f45ea4901
Downloading: org/clojure/clojure/1.10.3/clojure-1.10.3.pom from central
Downloading: org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-0.2.56.pom from central
Downloading: org/clojure/pom.contrib/0.3.0/pom.contrib-0.3.0.pom from central
Downloading: org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.pom from central
Downloading: org/clojure/clojure/1.10.3/clojure-1.10.3.jar from central
Downloading: org/clojure/core.specs.alpha/0.2.56/core.specs.alpha-0.2.56.jar from central
Downloading: org/clojure/spec.alpha/0.2.194/spec.alpha-0.2.194.jar from central
----- Error --------------------------------------------------------------------
Type:     java.lang.Exception
Message:  File does not exist: hl:compile

Karol Wójcik 2022-02-17T20:30:34.953199Z

Examples might not be up to date. Create a new project using template

Karol Wójcik 2022-02-17T20:30:51.562689Z

Then copy paste sources and deps

Karol Wójcik 2022-02-17T20:31:57.768029Z

Essentially the errors you are getting comes from bb tasks.

Karol Wójcik 2022-02-17T20:33:13.120769Z

Yeah. This example comes from HL < 0.6.0

Karol Wójcik 2022-02-17T20:33:23.377019Z

I should definetely update those.

2022-02-17T20:33:30.826929Z

Gotcha

2022-02-17T20:35:12.762349Z

Excuse my ignorance since I've pretty much only used lein , running this gives

nick@Nicks-MBP-2 code % clojure -X:new :template holy-lambda :name com.company/example-lambda :output holy-lambda-example
No function found on command line or in :exec-fn

Karol Wójcik 2022-02-17T20:36:24.506909Z

I’ll update the example and set up a minimal project with sqs, sts, s3, kms for you before work, but I’ll be able to do it only in 8-9 hours :)

❤️ 1
2022-02-17T20:36:44.533979Z

Wow, that is so kind of you! Thank you

Karol Wójcik 2022-02-17T20:37:02.256989Z

You can use lein new holy-lambda some-project if you like lein more

👍 1
2022-02-17T20:37:41.876039Z

Cool, I am open minded to using clj , just lacking experience

Karol Wójcik 2022-02-17T20:38:23.639389Z

The error you are getting means: „there is no „new” command in your user profile in global home deps.edn”.

2022-02-17T20:38:58.640969Z

Ah, I'll go set that up

Karol Wójcik 2022-02-17T20:39:26.177549Z

https://github.com/seancorfield/clj-new

Karol Wójcik 2022-02-17T20:39:54.266399Z

You can use a T alias if you have the lastest Clj CLI

👍 1
Karol Wójcik 2022-02-17T20:41:35.707519Z

I’m going to sleep. Will ping you tomorrow.

❤️ 1
2022-02-17T20:42:15.094329Z

Thanks again so much for your help. Sleep well

2022-02-18T01:04:28.805319Z

So I was able to successfully deploy with the clojure backend! 🙂 Still interested in switching to native for perf but this is a good start. However for whatever reason I'm not able to access the environment variables that I need in prod

{:AccessKeyId     (System/getenv "AWS_ACCESS_KEY_ID")
   :SecretAccessKey (System/getenv "AWS_SECRET_ACCESS_KEY")
   :SessionToken    (System/getenv "AWS_SESSION_TOKEN")})
Apparently it's not possible to get them with sts but they are supposed to be in these env variables, not sure what the issue is. https://forums.aws.amazon.com/thread.jspa?threadID=217933

2022-02-18T01:05:20.494379Z

I wanted to test it with sam local invoke as well but I wasn't sure how to get those env vars in that environment either

2022-02-18T01:06:28.283609Z

Btw the reason I need these is that I am using an AWS private endpoint and I am just writing an http request myself because I couldn't figure out how to do it with aws-cli

2022-02-18T01:07:57.840809Z

sqs is working as is, but I can't make the http request I need to push the correct data onto the sqs message body without those credentials

Karol Wójcik 2022-02-18T06:52:28.833399Z

Here is an updated version: https://github.com/FieryCod/holy-lambda/tree/master/examples/bb/native/cognitect.aws.api/src/sqs/example 1. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY are always present in Lambda production environment. To ensure Lambda may call a service X you have to add set of permissions in template.yml. This way AWS Lambda Service will be able to call service X. Lambda Service automatically creates a role for Lambda with the given permissions and populates the mentioned variables in function execution context. 2. When it comes to local environment your Lambda has the same permissions as your user specified in default profile. You can emulate a different used by switching a --profile in sam local invoke command. I don't understand your use case nor what is not working for you 😄 > sqs is working as is, but I can't make the http request I need to push the correct data onto the sqs message body without those credentials Could you elaborate?

❤️ 1
Karol Wójcik 2022-02-18T06:53:06.832959Z

What is behind this AWS private endpoint?