I'm working on a CloudFormation template and noticed an intricacy with Lambda that's new for me. Here's a snippet:
VersionLambdaRandom:
Type: AWS::Lambda::Version
Properties:
Description: Version testing.
FunctionName: !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaRandom}"
DependsOn: LambdaRandom
AliasLambdaRandom:
Type: AWS::Lambda::Alias
Properties:
FunctionName: !Sub "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaRandom}"
FunctionVersion: '1'
Name: TestDeploymentAlias
DependsOn:
- LambdaRandom
- VersionLambdaRandom
In the process of spinning this stack up and down, which deletes both the Version and Alias along with the Random Lambda that is not included here, I've noticed the version number doesn't reset when I create the stack again. Essentially, I'll create the stack again and will get a failure during the deployment along the lines of:
Function not found: arn:aws:lambda:us-east-1:<Acct#>:function:RandomLambdaFunction:1 (Service: AWSLambdaInternal; Status Code: 404; Error Code: ResourceNotFoundException)
Looking in the console, I can see a version of the newly created function was created successfully; however, it's now at version 2 rather than version 1. This seems like strange behavior to me since I completely deleted the stack, which includes deleting the lambda and the version.
What can I do to ensure the version I create when creating a stack always remains at one, besides switching the function name each time?
Lambda versions are immutable. That's the entire point of versioning - you can't change them once published, which includes deleting them. You have to delete your function as well to get read of its versions.
Related
Fairly new to Serverless and am having problems creating a dynamic path to an SSM parameter..... I have tried a fair few ideas but am sure that this is really close but its not quite there....
I'm trying to generate an ssm path as a custom variable that will then be used to populate a value for a Lambda function.
Here's the custom variable code
custom
securityGroupSsmPath:
dev: "${self:service}/${self:custom.stage}/rds/lambdasecuritygroup"
other: "${self:service}/${env:SHARED_INFRASTRUCTURE_ENV}/rds/lambdasecuritygroup"
securityGroupId: ${ssm:, "${self:custom.securityGroupSsmPath.${env:SHARED_INFRASTRUCTURE_ENV}, self:custom.securityGroupSsmPath.other}"}
And here is where it is referenced in the function
functions:
someLambda:
handler: build/handlers/someLambda/handler.handler
timeout: 60
memorySize: 256
vpc:
securityGroupIds:
- ${self:custom.securityGroupId}
And here is the error output. It seems like it is not resolving the ssm parameter
Serverless Error ----------------------------------------
Cannot resolve serverless.yml: Variables resolution errored with:
- Cannot resolve variable at "custom.securityGroupId": Parameter name: can't be prefixed with "ssm" (case-insensitive). If formed as a path, it can consist of sub-paths divided by slash symbol; each sub-path can be formed as a mix of letters, numbers and the following 3 symbols .-_
All help much appreciated,
Thanks!
Sam
In the end we tried numerous implementations and the issue seemed to boil down to trying to both retrieve the ssm value for securityGroupId and also parse and default the second variable within it.
The solution ended up being as follows where we removed the parsing/default variable from within ssm step. Additionally we had to remove some of the double quotes on the custom vars:-
custom
securityGroupSsmPath:
dev: ${self:service}/${self:custom.stage}/rds/lambdasecuritygroup
other: ${self:service}/${env:SHARED_INFRASTRUCTURE_ENV}/rds/lambdasecuritygroup
securityGroupId: ${self:custom.securityGroupSsmPath.${env:SHARED_INFRASTRUCTURE_ENV}, self:custom.securityGroupSsmPath.other}
functions:
someLambda:
handler: build/handlers/someLambda/handler.handler
timeout: 60
memorySize: 256
vpc:
securityGroupIds:
- ${ssm:/${self:custom.securityGroupId}}
I am trying to add another path to AWS Lambda that has been generated by code star.
I have tried to add the following events (in different commits) with the same failure behavior.
HelloWorld:
Type: AWS::Serverless::Function
Properties:
Events:
API:
Type:
Properties:
Path: /{proxy+}
Method: ANY
HelloWorld:
Type: AWS::Serverless::Function
Properties:
Events:
Decks_GetEvent:
Type: Api
Properties:
Path: /decks
Method: get
GenerateChangeSet step in code pipeline fails with the following unhelpful message:
Action execution failed
Failed to create change set. Current status: FAILED
When going to 'Details' Link of GenerateChangeSet step. It just takes me to Stack view without any particular stack or execution event selected.
What are the steps to troubleshoot this? Any suggestions on what could be causing this?
If it doesn't want to create a changeset, you presumably have a syntax error in your document. However, since you've not shared the CloudFormation template, that is hard to determine.
If you want to troubleshoot this, you can try to manually create a change set (that might provide more error information), or you can use cfn-lint to do some static code analysis on your CloudFormation template.
I'm particular new to Lambda and to AWS in general. I'm trying to setup a simple REST API Service with Lambda. I've used CloudFormat and CodePipeline to have a simple Express app.
I'm trying to figure out why during the deployment phase, during ExecuteChangeSet I have this error:
Errors found during import: Unable to create resource at path '/stations/{stationId}/allowedUsers': A sibling ({id}) of this resource already has a variable path part -- only one is allowed Unable to create resource at path '/stations/{stationId}/allowedUsers/{userId}': A sibling ({id}) of this resource already has a variable path part -- only one is allowed
This is what I have inside the template.yml
Events:
AllowedUsers:
Type: Api
Properties:
Path: /stations/{stationId}/allowedUsers
Method: get
AddAllowedUsers:
Type: Api
Properties:
Path: /stations/{stationId}/allowedUsers
Method: post
DeleteAllowedUsers:
Type: Api
Properties:
Path: /stations/{stationId}/allowedUsers/{userId}
Method: delete
GetAllowedUser:
Type: Api
Properties:
Path: /stations/{stationId}/allowedUsers/{userId}
Method: get
I searched a bit for this error but I'm not sure how to solve it.
For me, the issue was different from what is described in the GitHub issue Bryan mentioned.
I was using two different parameter names. Finishing the refactoring and using a single id name fixed the issue.
Example:
DeleteAllowedUsers:
Type: Api
Properties:
Path: /stations/{stationId}/allowedUsers/{id}
Method: delete
GetAllowedUser:
Type: Api
Properties:
Path: /stations/{stationId}/allowedUsers/{userId}
Method: get
Here is the walk around for this problem. It was posted on github by pettyalex.
link :https://github.com/serverless/serverless/issues/3785
You might encounter this issue when updating a variable path while using serverless ( and serverless.yaml ) to provision the AWS gatewayApi, here is a walk-around:
comment out the endpoint function to remove it completely
uncomment and deploy again
I am using Serverless framework.
I have created Cognito user pool in one stack and importing it into second stack.
When I assign the value of the Cognito User pool ID created in the first stack, to the environment variable it works.
But when I try to use it while creating a ARN for Cognito Authorizer, it doesn't work.
I get an error - Trying to populate non string value into a string for variable
Here is the snippet of my serverless.yml file.
service: myservice
plugins:
- serverless-pseudo-parameters
provider:
name: aws
runtime: go1.x
stage: dev
region: us-east-1
cognitoUserPoolId :
Fn::ImportValue: cloudformation-resources-${self:provider.stage}-CognitoUserPool
cognitoAppClientId :
Fn::ImportValue: cloudformation-resources-${self:provider.stage}-CognitoUserPoolClient
custom:
environment:
COGNITO_USER_POOL_ID : ${self:provider.cognitoUserPoolId}
COGNITO_APP_CLIENT_ID: ${self:provider.cognitoAppClientId}
functions:
myfunction:
handler: bin/handlers/myfunction
package:
exclude:
- "**/**"
include:
- ./bin/handlers/myfunction
events:
- http:
path: mypath
method: put
authorizer:
name: cognitoapiauthorizer
arn: arn:aws:cognito-idp:#{AWS::Region}:#{AWS::AccountId}:userpool/${self:provider.cognitoUserPoolId}
cors: true
Any issues related to indentation or the way it is being used in another variable like ARN?
I see you're trying to resolve the error Trying to populate non string value into a string for variable. In my experience, this means that the variable is empty. What happens if you hardcode the cognitoUserPoolId at the end of the ARN? Is the error resolved? I suspect it would be. Moving forward from there, you should take a closer look at how you declare that variable. Your usage of Fn::ImportValue may not working as intended.
Also, I would definitely run your YAML through a validator. There are too many extra blank lines, and extra spaces before the colons e.g. COGNITO_USER_POOL_ID : ${self:provider.cognitoUserPoolId}. These may be causing problems. Keep your YAML formatting tidy.
I'm trying to reference an edge lambda for cloudfront distribution in cloudformation.
What I have now is:
LambdaFunctionARN:
Fn::GetAtt: [BasicAuthLambdaFunction,Arn]
But I get this error:
An error occurred: GGGCloudFrontDistribution - The function
ARN must reference a specific function version. (The ARN must end with
the version number.)
So.. is there some kind of technique to reference the latest version of the function?
You can't use the latest version. You have to use a specific version as the documentation you linked states:
You must specify the ARN of a function version; you can't specify a Lambda alias or $LATEST.
If you are creating the Lambda function in your template, you can also create a version and use that.
BasicAuthLambdaFunctionVersion:
Type: "AWS::Lambda::Version"
Properties:
FunctionName:
Ref: BasicAuthLambdaFunction
# ...
LambdaFunctionARN:
Fn::GetAtt: [BasicAuthLambdaFunctionVersion,Arn]
Note that when updating the stack, a new version will not be created when the Lambda function code changes. You have to manually create and use a new version by changing the name of BasicAuthLambdaFunctionVersion to BasicAuthLambdaFunctionVersion2 or something else. To automate this, you can edit the template with a script before using it.
If you are using the Serverless Framework, take a look at:
https://github.com/silvermine/serverless-plugin-cloudfront-lambda-edge
https://github.com/serverless/serverless/issues/3944