Open milancermak opened 5 years ago
this is also useful for rolling back published versions (thru selecting just the alias) which I think is easier instead of repointing the alias to another version
In the meantime I solved this problem for our needs by post-processing the output of SAM. After we’ve run our templates through a cloudformation package we execute some custom code that goes through the template looking for SAM functions where AutoPublishAlias is true. When we find one we run this function to get the psuedo-random suffix that SAM appends to the end of the FunctionVersion that ultimately add into the template when it’s deployed:
function getHashSuffix(codeUri) {
const match = codeUri.match(/s3:\/\/([.a-zA-Z0-9_-]+?)\/([.a-zA-Z0-9_/-]+)/);
const codeObject = {
"S3Bucket": match[1],
"S3Key": match[2]
};
const code = utf8.encode(JSON.stringify(codeObject));
return crypto.createHash('sha1').update(code).digest('hex').slice(0,10);
}
Once we have the suffix, we can create our own aliases pointing at that version like:
template.Resources[`${r}Alias${suffix}`] = {
DeletionPolicy: 'Retain',
Properties: {
FunctionName: {
Ref: r
},
FunctionVersion: {
'Fn::GetAtt': [
`${r}Version${suffix}`,
'Version'
]
},
Name: packageData.deploy_version.replace(/\./g, '_')
},
Type: 'AWS::Lambda::Alias'
}
The key element here is the DeletionPolicy: ‘Retain’ and the fact that the alias is using the semantic version of our package replacing ‘.’ with ‘_’. The next time the template is deployed the hash will change and the new alias with the new version number will be created and even though the old one won’t be in the template anymore, it won’t be deleted because of the DeletionPolicy.
So every time we deploy two aliases are created both pointing at the new version - the numeric one SAM uses internally and for traffic shifting, and ours which other microservices can then reference.
@milancermak thank you for bringing this up. I agree that we should update the documentation to more clearly state these "best practice" decisions that SAM makes. Your other point is also a good one; I agree that we need to better support the "best practice" way of making Alexa Skills.
I haven't made an Alexa skill yet, could you post some of the thing you have found that are necessary when making an Alexa skill in SAM? I would like to be able to add features and documentation around this to make it easier for SAM users, as I have seen several people trying to do this. What are best practices that you have seen, and could we update or add examples that would make this process easier?
I don't know of any Alexa specific best practices when it comes to SAM. A skill is "just another Lambda function." However having the aliases behaviour as I've described in the issue would help.
There's an example in AWS blog: https://aws.amazon.com/blogs/compute/using-api-gateway-stage-variables-to-manage-lambda-functions/ which shows how to use stage variables to refer to Lambda alias. There're probably other examples and tools using this approach and it seems to make sense especially in small applications and APIs.
Also examples on AWS docs page for AWS::Lambda::Alias
show that you can use aliases for PROD
and TestingForMyApp
.
And seems like there's almost no difference between having
AutoPublishAlias: "staging"
and
StagingAlias:
Type: AWS::Lambda::Alias
Properties:
FunctionName: !Ref MyLambdaFunction
FunctionVersion: $LATEST
Name: "staging"
except first one points to a version
which is $LATEST
anyway.
@rinatio AutoPublishAlias
should be used with DeploymentPreference
for SAM and traffic shifting
I'm trying to find a workaround
With the template from the HelloWorld sample I have added a AWS::Lambda::Version
and AWS::Lambda::Alias
resources
The internal version of my development is passed as parameter like
sam deploy --parameter-overrides InternalVersion=v20241017
But for some reason not works... the lambda code is updated but the AWS::Lambda::Version
is not triggered in the change set??
So the tag is incorrectly applied to another version
Any clue? I can't see the error in my workaround
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
sam-demo
Sample SAM Template for sam-demo
Parameters:
InternalVersion:
Description: Internal version date
Type: String
Default: vYYYYMMDD
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Resources:
LastVersion:
Type: AWS::Lambda::Version
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
FunctionName: !Ref HelloWorldFunction
ProdAlias:
Type: AWS::Lambda::Alias
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
FunctionName: !Ref HelloWorldFunction
FunctionVersion: !GetAtt LastVersion.Version
Name: !Ref InternalVersion
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.11
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
This is a feature request to "do something like
AutoPublishAlias
, but better." Basically, I would like SAM to support exactly the process that is described in #298 and #304.Before I actually used
AutoPublishAlias
when deploying, my mental model of how it works was just as described in those issues. I did not expect deploying a new stage would remove the previous stage alias. I'm clearly not the only one who thought so. This is also the documented way on how to use aliases. Absolutely no document I read mentioned the best practice of separating stages to stacks. Not even in Safe Lambda deployments.Now of course I read the detailed and helpful explanation by @jfuss on these best practices. I see the value in it. But I also think there's merit to the original, intended way of having multiple aliases pointing to different version in the same stack. @jimcatts has a pretty convincing use case. I have another one - I have a hobby Alexa skill. It's really an overkill and needlessly complex to have 2 stacks (beta & prod) for an Alexa skill. I'm never going to run into the issues @jfuss mentioned are inherent in using the same stack for multiple stages.
Also, what is then the use case for
AutoPublishAlias
when the alias is pretty much always pointing to $LATEST. Or am I missing something?So I would ask the following: 1) Please update the documentation with best practices around multi-stage deployments, use of
AutoPublishAlias
where it's clearly mentioned it removes the "previous" alias, etc. 2) Please consider making the functionality mentioned above into a feature.