I get an "Internal transform" error when deploying this template. I use a Mapping to transform dev and prod settings. This works for single values but cloudformation is choking on trying to transform the Events config. This passes aws cloudformation validate-template whats wrong with my config?:
I use a Mapping to transform dev and prod settings. This works for single values but SAM is choking on trying to transform the Events config, whats wrong with my config?:
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Parameters:
env:
Description: Config map for transforming template with dev or prod values
Type: String
Default: dev
# Template uses !FindInMap along with env parameter to reference dev or prod values defined here
Mappings:
ConfigMap:
dev:
awsAccount: 'dev'
configFile: 'dev_config.yaml'
cloudwatchEvents: !Ref "AWS::NoValue"
prod:
awsAccount: 'prod'
configFile: 'prod_config.yaml'
cloudwatchEvents:
Schedule1:
Type: Schedule
Properties:
Schedule: rate(3 minutes)
Resources:
myfunction:
Type: 'AWS::Serverless::Function'
Properties:
CodeUri: ../build
Handler: lambda_function.lambda_handler
Runtime: python3.6
MemorySize: 128
Timeout: 30
Events:
!FindInMap
- ConfigMap
- !Ref env
- cloudwatchEvents
Environment:
Variables:
config_file: !FindInMap
- ConfigMap
- !Ref env
- configFile
Tags:
account: !FindInMap
- ConfigMap
- !Ref env
- awsAccount
blah: derp
Looks like you have a typo after !FindInMap, you are missing a colon after that. It should be !FindInMap:
Related
I have the following parameter in my CloudFormation script:
CloudFormationURL:
Type: String
Description: S3 URL for nested CloudFormation templates
Default: ""
This parameter covers the CloudFormation scripts in a nested folder of my deployment config.
I use it with a resource like this:
CloudWatchDashboardStack:
Type: "AWS::CloudFormation::Stack"
Properties:
TemplateURL: !Sub "${CloudFormationURL}/cloudwatch-dashboard.cfn.yaml"
Parameters:
AppName: !Ref AppName
DeployPhase: !Ref DeployPhase
DeveloperPrefix: !Ref DeveloperPrefix
Environment: !Ref Environment
Which works fine, and has worked for months.
I needed to add another resource, so I added this:
BatchDNSResources:
Type: "AWS::CloudFormation::Stack"
Properties:
Parameters:
AppName: !Ref AppName
Environment: !Ref Environment
DeveloperPrefix: !Ref DeveloperPrefix
DeployPhase: !Ref DeployPhase
AppVersion: !Ref AppVersion
SharedBucketName: !Ref SharedBucketName
S3Version: !Ref S3Version
HostedZone: !Ref HostedZone
VPCStackName: !FindInMap
- EnvironmentMap
- !Ref Environment
- VpcStackName
Company: !Ref Company
CostCenter: !Ref CostCenter
Team: !Ref Team
TemplateURL: !Sub "${CloudFormationURL}/batch-dns.cfn.yaml"
CloudFormation throws this error and then fails:
Parameters: [CloudFormationURL] must have values
Checking the changeset for the stack I can see the following value for the CloudFormationURL:
s3://application-shared-dev/application-name/qa/cf/nested/KShyDj205UK8mz6W_XUA5TnEF8nqPWHS
Checking the application predeploy logs I can see:
upload: deploy/cloudformation/templates/nested/batch-dns.cfn.yaml to s3://application-shared-dev/application-name/qa/cf/nested/KShyDj205UK8mz6W_XUA5TnEF8nqPWHS/batch-dns.cfn.yaml
And I can see the file in the S3 bucket.
If I remove BatchDNSResource the stack completes successfully.
What the heck am I missing here?
Sometimes, the smallest things will get you.
I had copied the Parameters from the master CloudFormation script, including this one, into the nested script:
CloudFormationURL:
Type: String
Description: S3 URL for nested CloudFormation templates
Default: ""
If you look closely, you will see that I did not pass the parameter into the nested script when calling the resource:
BatchDNSResources:
Type: "AWS::CloudFormation::Stack"
Properties:
Parameters:
AppName: !Ref AppName
Environment: !Ref Environment
DeveloperPrefix: !Ref DeveloperPrefix
DeployPhase: !Ref DeployPhase
AppVersion: !Ref AppVersion
SharedBucketName: !Ref SharedBucketName
S3Version: !Ref S3Version
HostedZone: !Ref HostedZone
VPCStackName: !FindInMap
- EnvironmentMap
- !Ref Environment
- VpcStackName
Company: !Ref Company
CostCenter: !Ref CostCenter
Team: !Ref Team
TemplateURL: !Sub "${CloudFormationURL}/batch-dns.cfn.yaml"
Because the CloudFormation console was saying the issue was with the BatchDNSResources I kept looking at the master script for the problem and missing the reference in the other script. There are two ways to solve this problem:
Keep CloudFormationURL as a parameter in the nested script (if you need it for some reason) and pass the value from the master script.
Remove the parameter from the nested script (if it is not needed)
Sometimes just asking for an extra set of eyeballs and getting a little rest will help you to find the issues. I want to leave this question/answer in place here because when I was searching for the error here and elsewhere no one ever mentioned (probably out of embarrassment) that the mistake is simply overlooking something like this. I hope this answer prompts others to check everything when they run across this type of error.
I am developping lambda with CloudFormation by SAM
My template.yaml is here.
It can be deployed, however this lambda is not set in VPC.
I want to put the lambda in default VPC (to access RDS)
Any setting can be used here or I should do something another??
(And, template makes IAmRole automatically, is there any way I can attach policy to it?? for example RDSFullAccess)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
python3.9 Sample SAM Template for chatbot-sam
Parameters:
DBNAME:
Type: String
DBUSER:
Type: String
DBPASSWORD:
Type: String
DBHOST:
Type: String
DBPORT:
Type: String
LINELONGLIVETOKEN:
Type: String
Globals:
Function:
Timeout: 30
Environment:
Variables:
DBNAME: !Ref DBNAME
DBUSER: !Ref DBUSER
DBPASSWORD: !Ref DBPASSWORD
DBHOST: !Ref DBHOST
DBPORT: !Ref DBPORT
LINELONGLIVETOKEN: !Ref LINELONGLIVETOKEN
Resources:
WebhookFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
Architectures:
- x86_64
Events:
Webhook:
Type: Api
Properties:
Path: /webhook
Method: post
Metadata:
Dockerfile: Dockerfile.webhook
DockerContext: ./chatbotapp
DockerTag: python3.9-v1
Outputs:
WebhookApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/webhook/"
WebhookFunction:
Description: "Webhook Lambda Function ARN"
Value: !GetAtt WebhookFunction.Arn
WebhookFunctionIamRole:
Description: "Implicit IAM Role created for Webhook function"
Value: !GetAtt WebhookFunctionRole.Arn
I updated.
Attaches VpcConfig and Policies , however it doesn't look change.
lambda -> setting -> vpc, there is no vpc setting and can't find the clue it belongs to SecurityGroup and Subnet
Policies: AWSLambdaVPCAccessExecutionRole
VpcConfig:
SubnetIds:
- subnet-fb6fa4d0
- subnet-bf8ab8e4
SecurityGroupIds:
- sg-0641506b4ec3782de
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
python3.9 Sample SAM Template for chatbot-sam
Parameters:
DBNAME:
Type: String
DBUSER:
Type: String
DBPASSWORD:
Type: String
DBHOST:
Type: String
DBPORT:
Type: String
LINELONGLIVETOKEN:
Type: String
Globals:
Function:
Timeout: 30
Environment:
Variables:
DBNAME: !Ref DBNAME
DBUSER: !Ref DBUSER
DBPASSWORD: !Ref DBPASSWORD
DBHOST: !Ref DBHOST
DBPORT: !Ref DBPORT
LINELONGLIVETOKEN: !Ref LINELONGLIVETOKEN
Resources:
WebhookFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
Architectures:
- x86_64
Events:
Webhook:
Type: Api
Properties:
Path: /webhook
Method: post
Policies: AWSLambdaVPCAccessExecutionRole
VpcConfig:
SubnetIds:
- subnet-fb6fa4d0
- subnet-bf8ab8e4
SecurityGroupIds:
- sg-0641506b4ec3782de
Metadata:
Dockerfile: Dockerfile.webhook
DockerContext: ./chatbotapp
DockerTag: python3.9-v1
Outputs:
WebhookApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/webhook/"
WebhookFunction:
Description: "Webhook Lambda Function ARN"
Value: !GetAtt WebhookFunction.Arn
WebhookFunctionIamRole:
Description: "Implicit IAM Role created for Webhook function"
Value: !GetAtt WebhookFunctionRole.Arn
You'll need to add a VpcConfig to the properties of your function definition. You can see an example of how to use that here.
You can also add policies to the default role that is made for the function, or you can supply your own role, in which case the default role will not be created.
This is my cft for my aplication sharing below and it is created successfully for first time ,while I am updating the cft (codechange) ,the LambdaAllias is stuck in Update In Progress stage .Could someone please guide me on this .
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AWS Serverless Quarkus HTTP - Flight Info svc
FlightInfoService:
Type: AWS::Serverless::Function
Properties:
Handler: not.used.in.provided.runtime
Runtime: provided
Role:
Fn::ImportValue:
'Fn::Sub': '${InfraStackName}-FlightInfoSvcLambdaExecutionRoleArn'
CodeUri: component1/function.zip
MemorySize: 1024
Timeout: 900
AutoPublishAlias: live
ProvisionedConcurrencyConfig:
ProvisionedConcurrentExecutions: 1
DeploymentPreference:
Type: !Ref SetDeploymentPreferencetype
Role:
Fn::ImportValue:
'Fn::Sub': '${InfraStackName}-FlightInfoSvcLambdaCodeDeployRoleArn'
TriggerConfigurations:
- TriggerTargetArn: !Ref AlertTopic
TriggerName: DeploymentAlerts
TriggerEvents:
- DeploymentStart
- DeploymentSuccess
- DeploymentFailure
- DeploymentStop
- DeploymentRollback
Alarms:
# A list of alarms that you want to monitor
- !Ref FlightInfoSvcErrorMetricGreaterThanZeroAlarm
- !Ref FlightInfoSvcLatestVersionErrorMetricGreaterThanZeroAlarm
Hooks:
# Validation Lambda functions that are run before & after traffic shifting
PreTraffic: !Ref FlightInfoSvcPreTrafficHook
PostTraffic: !Ref FlightInfoSvcPostTrafficHook
Environment:
Variables:
REFERENCE_DATA_SERVICE_BASE_PATH: !Ref RefDataSvcBasePath
REFERENCE_DATA_SERVICE_API_GATEWAY_ID: !Ref RefDataSvcGatewayId
LOG_LEVEL: INFO
DISABLE_SIGNAL_HANDLERS: true
AWS_SECRET_ENDPOINT: secretsmanager.us-east-1.amazonaws.com
AWS_SECRET_REGION: us-east-1
ADD_ON_UPDATE_FAILED_FLAG: true
FLIGHT_ORIGIN_DATE_TTL: 60
Tracing: Active
VpcConfig:
SecurityGroupIds:
- !Ref SecurityGroups
SubnetIds:
Fn::Split:
- ","
- !Ref Subnets
I removed the reference variables and parameter section ,only keeping the function name where I am getting issue .
I create CloudFormation template for my AWS Lambda function and I need to specify different values of environment variables for different lambda aliases.
My template looks like:
AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Description: Lambda function configuration
Resources:
EndpointLambda:
Type: "AWS::Lambda::Function"
Properties:
FunctionName: "endpoint-lambda"
Handler: "com.test.aws.RequestHandler::handleRequest"
Runtime: java8
Code:
S3Bucket: "lambda-functions"
S3Key: "test-endpoint-lambda-0.0.1.jar"
Description: Test Lambda function
MemorySize: 256
Timeout: 60
Environment:
Variables:
ES_HOST: test-es-host-url
ES_ON: true
ES_PORT: 443
ES_PROTOCOL: https
REDIS_URL: test-redis-host-url
QaLambdaAlias:
Type: "AWS::Lambda::Alias"
Properties:
FunctionName: !Ref EndpointLambda
FunctionVersion: 1
Name: "QA"
Description: "QA alias"
ProdLambdaAlias:
Type: "AWS::Lambda::Alias"
Properties:
FunctionName: !Ref EndpointLambda
FunctionVersion: 1
Name: "Prod"
Description: "Production alias"
As you see, I have two aliases - QA and Prod and bunch of environment variables. I specified variables with common values in lambda function declaration. But I need to declare for QA alias env. variable's values related to QA, and for Prod alias - values for Prod environment. Any ideas how can I do that?
You can use CloudFormation Parameters to do this. As a quick example:
Parameters:
LambdaRuntime:
Type: String
Default: 'java8'
Description: What Lambda runtime do we use?
Resources:
QaLambdaAlias:
Type: "AWS::Lambda::Alias"
Properties:
FunctionName:
Ref: EndpointLambda
FunctionVersion: 1
Name: "QA"
Description: "QA alias"
Runtime:
Ref: LambdaRuntime
Then, if you want to use a different parameter, when you deploy via CLI, you can override with parameter-overrides like this:
aws cloudformation deploy --stack-name MyStack --template-file \
CloudFormation/MyStack.yaml --capabilities CAPABILITY_IAM \
--parameter-overrides LambdaRuntime=nodejs8.10
I create CloudFormation template for my AWS API Gateway and Lambda function and I need to connect specific API Gateway stage to specific Lambda alias. I have two aliases - QA and Prod, and two API stages (QA & Prod too), in CloudFormation template it looks like:
AWSTemplateFormatVersion: "2010-09-09"
Transform: "AWS::Serverless-2016-10-31"
Description: Lambda function configuration
Resources:
EndpointLambda:
Type: "AWS::Lambda::Function"
Properties:
FunctionName: "endpoint-lambda"
Handler: "com.test.aws.RequestHandler::handleRequest"
Runtime: java8
Code:
S3Bucket: "lambda-functions"
S3Key: "test-endpoint-lambda-0.0.1.jar"
Description: Test Lambda function
MemorySize: 256
Timeout: 60
Environment:
Variables:
ES_HOST: test-es-host-url
ES_ON: true
ES_PORT: 443
ES_PROTOCOL: https
REDIS_URL: test-redis-host-url
QaLambdaAlias:
Type: "AWS::Lambda::Alias"
Properties:
FunctionName: !Ref EndpointLambda
FunctionVersion: 1
Name: "QA"
Description: "QA alias"
ProdLambdaAlias:
Type: "AWS::Lambda::Alias"
Properties:
FunctionName: !Ref EndpointLambda
FunctionVersion: 1
Name: "Prod"
Description: "Production alias"
RestApi:
Type: "AWS::ApiGateway::RestApi"
Properties:
Name: "test-rest-api"
Description: "Test REST API"
RestApiResource:
Type: "AWS::ApiGateway::Resource"
Properties:
RestApiId: !Ref "RestApi"
ParentId: !GetAtt "RestApi.RootResourceId"
PathPart: "/test"
RestApiDeployment:
Type: "AWS::ApiGateway::Deployment"
Properties:
RestApiId: !Ref "RestApi"
QaRestApiStage:
Type: "AWS::ApiGateway::Stage"
Properties:
DeploymentId: !Ref "RestApiDeployment"
RestApiId: !Ref "RestApi"
StageName: "qa"
ProdRestApiStage:
Type: "AWS::ApiGateway::Stage"
Properties:
DeploymentId: !Ref "RestApiDeployment"
RestApiId: !Ref "RestApi"
StageName: "prod"
How can I describe in template that QA API stage should call QA alias of Lambda function, and Prod stage - Prod alias?
To begin with find out how to do it using the GUI. There some documentation about what you want to do here. Theres some extra permissions you'll need to add aswell if this is the first time you've set this up which are included here -
https://docs.aws.amazon.com/apigateway/latest/developerguide/stage-variables.html
But for a quick answer what your looking for is $:{stageVariables.stage} what this does is links the alias of the lambda you want to trigger. In the GUI it'd look something like this:
What this will do is allow your lambda to trigger a certain alias. Once this is entered you'll be able to see a new option when using the Testing feature in the API gateway. So here you'd specify QA.
So, to reflect this in Cloudformation we need to do something similar -
RestApi:
Type: "AWS::ApiGateway::RestApi"
Properties:
Name: "test-rest-api"
Description: "Test REST API"
paths:
/ExamplePath:
put:
#Here will go all the configuration setting you want
#Such as security, httpMethod, amd passthroughBehavior
#But what you need is
uri: 'arn:aws:apigateway:${AWS:Region}:lambda:path/2-15/03/31/functions/${LambdaARN}:${!stageVariables.stage}/invocations'
More info on this can be found here:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apitgateway-method-integration.html what you'll want to see is at the very bottom of the page.
Hope this helps!