I'm trying to dynamically pass in options to resolve when deploying my functions with serverless but they're always null or hit the fallback.
custom:
send_grid_api: ${opt:sendgridapi, 'missing'}
SubscribedUsersTable:
name: !Ref UsersSubscriptionTable
arn: !GetAtt UsersSubscriptionTable.Arn
bundle:
linting: false
provider:
name: aws
lambdaHashingVersion: 20201221
runtime: nodejs12.x
memorySize: 256
stage: ${opt:stage, 'dev'}
region: us-west-2
environment:
STAGE: ${self:provider.stage}
SEND_GRID_API_KEY: ${self:custom.send_grid_api}
I've also tried:
environment:
STAGE: ${self:provider.stage}
SEND_GRID_API_KEY: ${opt:sendgridapi, 'missing'}
both yield 'missing', but why?
sls deploy --stage=prod --sendgridapi=xxx
also fails if I try with space instead of =.
Edit: Working Solution
In my github action template, I defined the following:
- name: create env file
run: |
touch .env
echo SEND_GRID_API_KEY=${{ secrets.SEND_GRID_KEY }} >> .env
ls -la
pwd
In addition, I explicitly set the working directory for this stage like so:
working-directory: /home/runner/work/myDir/myDir/
In my serverless.yml I added the following:
environment:
SEND_GRID_API_KEY: ${env:SEND_GRID_API_KEY}
sls will read the contents from the file and load them properly
opt is for serverless' CLI options. These are part of serverless, not your own code.
You can instead use...
provider:
...
environment:
...
SEND_GRID_API_KEY: ${env:SEND_GRID_API_KEY}
And pass the value as an environment variable in your deploy step.
- name: Deploy
run: sls deploy --stage=prod
env:
SEND_GRID_API_KEY: "insert api key here"
Related
Following this tutorial, https://docs.gitlab.cn/14.0/ee/user/project/clusters/serverless/aws.html#serverless-framework
Created a function in AWS Lambda called create-promo-animation
Created a /src/handler.js
"use strict";
module.exports.hello = async (event) => {
return {
statusCode: 200,
body: JSON.stringify(
{
message: "Your function executed successfully!",
},
null,
2
),
};
};
Created gitlab-ci.yml
stages:
- deploy
production:
stage: deploy
before_script:
- npm config set prefix /usr/local
- npm install -g serverless
script:
- serverless deploy --stage production --verbose
environment: production
Created serverless.yml
service: gitlab-example
provider:
name: aws
runtime: nodejs14.x
functions:
create-promo-animation:
handler: src/handler.hello
events:
- http: GET hello
pushed to GitLab, Pipe run well
But code is not updating in AWS, why?
Is it possible to add some conditions to this way of using templates?
I would like to use conditions based on branches.
If branch = main or development > deploy to dev
Only if branch > main, deploy to staging
The complete Pipeline:
trigger:
batch: true
branches:
include:
- main
pool: 'On-Prem Pool'
variables:
- group: ContainerRegistry
- group:xyz
- name: appName
value: 'xyz'
- name: dockerfilePath
value: '**/Dockerfile'
stages:
# Build App and push to container registry
- stage: Build
displayName: Build and push to container registry
jobs:
- job: Build
displayName: Build job
pool: 'On-Prem Pool'
steps:
- task: Docker#2
displayName: Login to ACR
inputs:
command: login
containerRegistry: $(registryServiceConnection)
- task: Docker#2
displayName: Build container image
inputs:
command: build
repository: $(appName)
dockerfile: $(dockerfilePath)
containerRegistry: $(registryServiceConnection)
tags: $(Build.BuildId)
- task: Docker#2
displayName: Push container image
inputs:
command: push
repository: $(appName)
containerRegistry: $(registryServiceConnection)
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Don´t push to ACR on Pull Requests
# Infrastructure
# Lint the Bicep file.
- stage: Lint
jobs:
- template: pipeline-templates/lint.yml
# Deploy to the dev environment.
- template: pipeline-templates/deploy.yml
parameters:
environmentType: Development
resourceGroupName: rg-xx
appSuffix: xyz
costCenter: 'xyz'
serviceConnectionName: 'SVCxx'
dockerRegistryPassword: $(dockerRegistryPassword)
dockerRegistryUserName: $(dockerRegistryUserName)
containerTag: $(Build.BuildId)
registryUrl: $(registryUrl)
cpuCores: 0.5
memory: 1
minReplicas: 0
maxReplicas: 1
# Deploy to the staging environment.
- template: pipeline-templates/deploy.yml
parameters:
environmentType: Staging
resourceGroupName: rg-xxx-001
appSuffix: xyz
costCenter: 'xyz'
serviceConnectionName: 'SVCxxx'
dockerRegistryPassword: $(dockerRegistryPassword)
dockerRegistryUserName: $(dockerRegistryUserName)
containerTag: $(Build.BuildId)
registryUrl: $(registryUrl)
cpuCores: 0.5
memory: 1
minReplicas: 1
maxReplicas: 2
)
And it is the last two -templates I would like to apply some conditions on.
Many thanks!
During my test, I edited my build.yaml as below. And when I ran it, the second template could evaluate correctly but the third one not, and thus, the third template was skipped.
pool:
vmImage: windows-latest
stages:
- template: template.yml
parameters:
env: dev
- ${{ if eq(variables['Build.QueuedBy'], 'Ceeno') }}:
- template: template.yml
parameters:
env: qa
- ${{ if eq(variables['Build.QueuedBy'], 'Vacee') }}:
- template: template.yml
parameters:
env: prod
And if you are looking for the evaluation for other method or other scenario, you could share with me for further investigations.
Yes I solved it in a similar way;
- stage: BuildDeployProd
displayName: Build and deploy Prod env
jobs:
- template: pipeline-templates/deploy.yml
parameters:
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
I am having problems using two stages being dev and prod. I followed instructions with serverless --stage dev but this gives an error when deploying with my serverless.yml file:
custom:
STAGES: ${opt:stage, self:provider.stage}
settings:
DOMAIN:
dev: ["foo", "bar.com"]
prod: ["tee", "mee.money"]
DISTRIBUTION:
dev: "25asdfg342343"
#prod: "sdfg454545f"
ALIASES:
dev: ["foo.bar.com"]
prod: ["tee.mee.money"]
CERTIFICATE:
dev: "arn:aws:acm:us-west-1:123523523:certificate/asdfasd-asdfasdf12345234234"
prod: "arn:aws:acm:us-west-1:12355:certificate/tdsaasdf52345234234rfdswf"
nextHostApp:
component: "./node_modules/#sls-next/serverless-component"
inputs:
domain: ${self:custom.settings.DOMAIN.${self:custom.STAGES}}
cloudfront:
distributionId: ${self:custom.settings.DISTRIBUTION.${self:custom.STAGES}}
comment: "This distribution will host my MF architecture of Lambda#Edges"
aliases: ${self:custom.settings.ALIASES.${self:custom.STAGES}}
certificate:
cloudFrontDefaultCertificate: false
acmCertificateArn: ${self:custom.settings.CERTIFICATE.${self:custom.STAGES}}
minimumProtocolVersion: "TLSv1.2_2019"
This is the error that pops up:
0s › Template › Error: invalid reference ${self:custom.STAGES}
Am I doing something wrong on my side with the ${self:custom.STAGES}? I would appreciate any help!
I've debugged my application, and identified a problem. I have 2 REST API Gateway, and it seems like since they both bind on the same endpoint, the first one will recieve the call that the second one should handle.
Here's my template.yaml
Resources:
mysampleapi1:
Type: 'AWS::Serverless::Function'
Properties:
Handler: packages/mysampleapi1/dist/index.handler
Runtime: nodejs14.x
CodeUri: .
Description: ''
MemorySize: 1024
Timeout: 30
Role: >-
arn:aws:iam:: [PRIVATE]
Events:
Api1:
Type: Api
Properties:
Path: /users
Method: ANY
Environment:
Variables:
NODE_ENV: local
Tags:
STAGE: local
mysampleapi2:
Type: 'AWS::Serverless::Function'
Properties:
Handler: packages/mysampleapi2/dist/index.handler
Runtime: nodejs14.x
CodeUri: .
Description: ''
MemorySize: 1024
Timeout: 30
Role: >-
arn:aws:iam:: [PRIVATE]
Events:
Api1:
Type: Api
Properties:
Path: /wallet
Method: ANY
Environment:
Variables:
NODE_ENV: local
Tags:
STAGE: local
When I send a HTTP request for mysampleapi2
Here's what's happening in the logs using the startup command
sam local start-api --port 3001 --log-file /tmp/server-output.log --profile personal --debug
2022-04-27 18:2:34,953 | Mounting /home/mathieu_auclair/Documents/Project/repositories/server as /var/task:ro,delegated inside runtime container
2022-04-27 18:20:35,481 | Starting a timer for 30 seconds for function 'mysampleapi1'
2022-04-27 18:21:05,484 | Function 'mysampleapi1' timed out after 30 seconds
2022-04-27 18:21:46,732 | Container was not created. Skipping deletion
2022-04-27 18:21:46,732 | Cleaning all decompressed code dirs
2022-04-27 18:21:46,733 | No response from invoke container for mysampleapi1
2022-04-27 18:21:46,733 | Invalid lambda response received: Lambda response must be valid json
Why is my mysampleapi2 not picking the HTTP call? If I run them in separate template files using different ports, then it works... why is that?
After launching my lambda in separate processes, I discovered that there's an issue in my configuration for the second service.
The issue still occured after this launcher
echo "" > /tmp/server-output-1.log
sam local start-api --port 3001 --log-file /tmp/server-output-1.log --template .template.1.yaml --debug &
tail -f /tmp/server-output-1.log &
echo "" > /tmp/server-output-2.log
sam local start-api --port 3002 --log-file /tmp/server-output-2.log --template .template.2.yaml --debug &
tail -f /tmp/server-output-2.log &
I noticed when I exported my configuration, for one of the services, there's the following in the template.yaml
Path: '/{proxy+}'
without the proxy line, the lambda handler just never gets called for some reason
I am trying to deploy my serverless project locally with LocalStack and serverless-local plugin. When I try to deploy it with serverless deploy it throws an error and its failing to create the cloudformation stack.But, I manage to create the same stack when I deploy the project in to real aws environment. What is the possible issue here. I checked answers in all the previous questions asked on similar issue, nothing seems to work.
docker-compose.yml
version: "3.8"
services:
localstack:
container_name: "serverless-localstack_main"
image: localstack/localstack
ports:
- "4566-4597:4566-4597"
environment:
- AWS_DEFAULT_REGION=eu-west-1
- EDGE_PORT=4566
- SERVICES=lambda,cloudformation,s3,sts,iam,apigateway,cloudwatch
volumes:
- "${TMPDIR:-/tmp/localstack}:/tmp/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
serverless.yml
service: serverless-localstack-test
frameworkVersion: '2'
plugins:
- serverless-localstack
custom:
localstack:
debug: true
host: http://localhost
edgePort: 4566
autostart: true
lambda:
mountCode: True
stages:
- local
endpointFile: config.json
provider:
name: aws
runtime: nodejs12.x
lambdaHashingVersion: 20201221
stage: local
region: eu-west-1
deploymentBucket:
name: deployment
functions:
hello:
handler: handler.hello
Config.json (which has the endpoints)
{
"CloudFormation": "http://localhost:4566",
"CloudWatch": "http://localhost:4566",
"Lambda": "http://localhost:4566",
"S3": "http://localhost:4566"
}
Error in Localstack container
serverless-localstack_main | 2021-06-04T17:41:49:WARNING:localstack.utils.cloudformation.template_deployer: Error calling
<bound method ClientCreator._create_api_method.<locals>._api_call of
<botocore.client.Lambda object at 0x7f31f359a4c0>> with params: {'FunctionName':
'serverless-localstack-test-local-hello', 'Runtime': 'nodejs12.x', 'Role':
'arn:aws:iam::000000000000:role/serverless-localstack-test-local-eu-west-1-lambdaRole',
'Handler': 'handler.hello', 'Code': {'S3Bucket': '__local__', 'S3Key':
'/Users/charles/Documents/Practice/serverless-localstack-test'}, 'Timeout': 6,
'MemorySize': 1024} for resource: {'Type': 'AWS::Lambda::Function', 'Properties':
{'Code': {'S3Bucket': '__local__', 'S3Key':
'/Users/charles/Documents/Practice/serverless-localstack-test'}, 'Handler':
'handler.hello', 'Runtime': 'nodejs12.x', 'FunctionName': 'serverless-localstack-test-
local-hello', 'MemorySize': 1024, 'Timeout': 6, 'Role':
'arn:aws:iam::000000000000:role/serverless-localstack-test-local-eu-west-1-lambdaRole'},
'DependsOn': ['HelloLogGroup'], 'LogicalResourceId': 'HelloLambdaFunction',
'PhysicalResourceId': None, '_state_': {}}
I fixed that problem using this plugin: https://www.serverless.com/plugins/serverless-deployment-bucket
You need to make some adjustments in your files.
Update your docker-compose.yml, use the reference docker compose from
localstack, you can check it here.
Use a template that works correctly, AWS docs page have several
examples, you can check it here.
Run it with next command aws cloudformation create-stack --endpoint-url http://localhost:4566 --stack-name samplestack --template-body file://lambda.yml --profile dev
You can also run localstack using Python with next commands
pip install localstack
localstack start