Selectively update Lambda version description for a stack - amazon-web-services

We have a setup where we deploy a stack that contains a bunch of Lambdas.
We want to version these lambdas (so far so good) and we want to update the version description to contain say then commit-id that was responsible for the new version (or some other identifier).
What happens in our current approach:
We pass the commit-id in to the template
We set the description of each Lambda to contain the commit-id
CloudFormation takes the new version description (with the current commit-id) to be a change to the Lambda definition but we don't change all Lambdas every time
The version description is immutable so if the Lambda hasn't actually changed and we try to set a new one, the entire change set fails
Setting the description of only the changed lambdas is hard because we don't have that information at this stage.
Is there a straight-forward way for us to set the description for a lambda version to something that correlates with the contents?

Related

AWS CDK conditional ImportValue

I'm importing an ARN from another stack with the cdk.Fn.importValue method. This works fine if I know that the output value is always present, but I don't know how to handle the case when the value I try to import is optional.
How can I get something similar to: (checking if the value exists before importing it)
if(value exists) {
cdk.Fn.importValue("value")
}
AFAIK there currently is no way in CDK to perform a lookup of a CloudFormation exports during synthesis time.
If you don't want to fiddle around with performing CloudFormation API calls with the aws-sdk before creating the CDK stack, in my opinion the most elegant way to share conditional values between stacks, is to use SSM parameters instead of CloudFormation exports.
SSM parameters can be looked up during synthesis time. See docs: https://docs.aws.amazon.com/cdk/v2/guide/get_ssm_value.html
So, with StringParameter.valueFromLookup you are then able to only use the value if it exists (IIRC the method throws an error if the parameter doesn't exist, so try-catch is your friend here, but not 100% sure).

Does Cloudformation support update links?

To help people create a Cloudformation stack, I can generate links to parameterized Cloudformation templates:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-create-stacks-quick-create-links.html
Question: Is there a way to generate another link to update the previously created Cloudformation stack?
What I tried and what doesn't work:
I generated a link to create stack "ABC" using template Template1.
​I generated a link to create stack "ABC", with a slightly modified template Template2.
What happens is that Cloudformation creates the first "ABC" stack based on Template1, but then complains that the "ABC" stack already exists when trying to create a stack with the same name using Template2.
I kind of expected this behavior, but I assumed that -- since stack names are unique -- that it would offer to apply updates instead of trying to create (and fail) to create the stack.

Best Method to Manipulate a CfnParameter String in aws-cdk

I'm trying in vain to do this. Here is the scenario:
We are creating a CloudFormation Stack that will generate a CodePipeline, that will pull another stack definition from git and deploy it, using the CloudFormationCreateUpdateStackAction
The repo and branch etc. are provided as CfnParamaters and the subsequent stack name we would like to base off a concatenation of the repo name and branch name.
However in some cases the repo might be named with an underscore or other special character that is invalid for a stackName.
I've attempted to manipulate the parameter strings using Macro's but I didnt get anywhere near something useful and running a .replace() function on the repoStr.valueAsString property modifies the CDK's "Token" pointer, not the resulting paramter which is declared at runtime.
Any ideas?
There are two options I can see:
First is to read the actual parameter value at synthesis time, then you can use the .replace function on parameter value. https://docs.aws.amazon.com/cdk/api/latest/docs/#aws-cdk_aws-ssm.StringParameter.html#static-value-wbr-from-wbr-lookupscope-parametername
Second is to use CloudFormation intristic function to split the parameter and join the fragments back in allowed manner. https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-split.html https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html

How to work around Cfn action's character limit in CodePipeline

Using the AWS CDK, I have a CodePipeline that produces build artifacts for 5 different Lambda functions, and then passes those artifacts as parameters to a CloudFormation template. The basic setup is the same as this example, and the CloudFormation deploy action looks basically like this:
new CloudFormationCreateUpdateStackAction({
actionName: 'Lambda_CFN_Deploy',
templatePath: cdkBuildOutput.atPath('LambdaStack.template.json'),
stackName: 'LambdaDeploymentStack',
adminPermissions: true,
parameterOverrides: {
...props.lambdaCode.assign(lambdaBuildOutput.s3Location),
// more parameter overrides here
},
extraInputs: [lambdaBuildOutput],
})
However, when I try to deploy, I get this error:
1 validation error detected: Value at 'pipeline.stages.3.member.actions.1.member.configuration' failed to satisfy constraint:
Map value must satisfy constraint:
[Member must have length less than or equal to 1000, Member must have length greater than or equal to 1]
The CodePipeline documentation specifies that values in the Configuration property of the ActionDeclaration can be up to 1000 characters. If I look at the YAML output from cdk synth, the ParameterOverrides property comes out to 1351 characters. So that's a problem.
How can I work around this issue? I may need to add more Lambda functions in the future, so this problem will only get worse. Part of the problem is that the CDK code inserts 'LambdaSourceBucketNameParameter' and 'LambdaSourceObjectKeyParameter' in each bucket/object pair name in the configuration output, putting me at 61 * 5 = 305 characters lost just to being verbose. Could I get part of the way there by overriding those generated names?
I got some assistance from a CDK maintainer here, which let me get well under the 1000-character limit. Reproducing the workaround here:
LambdaSourceBucketNameParameter and LambdaSourceObjectKeyParameter are just the default parameter names. You can create your own:
lambda.Code.fromCfnParameters({
bucketNameParam: new CfnParameter(this, 'A'),
objectKeyParam: new CfnParameter(this, 'B'),
});
You can also name Artifacts explicitly, thus saving a lot of characters over the defaults:
const sourceOutput = new codepipeline.Artifact('S');
EDIT 10-Jan-2020
I finally got a response from AWS Support regarding the issue:
I've queried the CodePipeline team and searched though the current development workflows and couldn't find any current activity related to increasing the limit for parameters passed to a CloudFormation stack or any alternative method for this action, so we have issued a feature request based on your request for our development team.
I'm not able to provide an estimated time for this feature to be available, but you can follow the release on new features through the CloudFormation and CodePipeline official pages to check when the new feature will be available.
So for now, it looks like the CfnParameter workaround is the best option.

Intermediate Cloud formation template with values filled from Dynamic CFT

Would like know if CFT API's or logs from Cloudtrail can provide any intermediate CFT before or while creating the resources. When I mean intermediate CFT(s) , We know the CFT can be kind of dynamic in the form of parameters /condition/mappings/functions those are to be evaluated at run time. I would like to know if this CFT can generate the processed CFT (with all the processed rules/parameters from input/functions...) as though it looks like static for the resource creation process. This approach really helps us in validating the real CFT that is going to be executed with all the values replaced. I'm just looking for the another CFT API. something like ,
String staticCFT = cftClient.getActualCFT("cft_location\cft.json","parameters"...);
If this feature is available , it really saves time and don't have to wait until all the resources are created with wrong values because of wrong logic in CFT.
What you can actually create is what I call a "dummy template". I use it at work as a stand-in to an actual template with real resources which would take time to execute. The dummy template has only one resource which does not actually do anything. I use a CustomResource to invoke a "HelloWorld" Lambda function. This is to get around the restriction that a CFT must have at least one resource. The template also has a bunch of parameters and all those parameters are simply supplied directly to the Outputs section. The execution of this template will hardly take a few seconds and based on the parameters and outputs, you can figure out whether your top-level template is passing in the expected values of the parameters. You can invoke the dummy template from within the top-level template.