Using cfn-lint in nested stacks - amazon-web-services

When using cfn-lint in nested stacks, it seems that the parameters of the root stack are not passed over to the child stack, so the check doesn't work properly.
cfn-lint will not find any errors if you enter the wrong parameters in the ROOT stack.
root stack
Resources:
VPC:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: dir/child.yml
Parameters:
If you put the S3 path in the templateURL, it will not be checked,
Local path returns error W3002.
This stack deploys normally.
Can you help me ?

Related

CloudFormation passing variables from one stack to another

I have a situation where I want to pass the output parameter from one stack to the Parameters of another stack. I know about the Outputs area and the Fn::ImportValue but I have to declair a separate variable in stack #2 or else I get errors.
In Stack 1:
Parameters:
EnvironmentName:
Type: String
Default: production
Description: "A friendly environment name that will be used for namespacing all cluster resources. Example: staging, qa, or production"
...
Outputs:
EnvironmentName:
Description: The deployment mode of this and subsequent stacks.
Value: !Ref EnvironmentName
Export:
Name: !Ref EnvironmentName
In stack #2 I have:
Parameters:
EnvironmentName:
Type: String
Default: production
Description: "A friendly environment name that will be used for namespacing all cluster resources. Example: staging, qa, or production"
I would like to have the Environment name not having to be declared twice. But I can't do:
Parameters:
EnvironmentName:
Type: String
Default: Fn::ImportValue {$EnvironmentName}
Description: "A friendly environment name that will be used for namespacing all cluster resources. Example: staging, qa, or production"
There are a few things I could try, one post suggested using FindInMap and put the env names in the map. That just seems odd and again, I've not tried that. The other method is Nested Stacks but I don't want to end up with one huge template file.
You can't do that. It simply not possible and CFN does not support functions in Parameter defaults or Mappings.

Using a Resource from a Nested Stack in Another Nested Stack with DependsOn

I have been refactoring what has become a rather large stack because it is brushing up against size limits for CloudFormation scripts on AWS. In doing so I have had to resolve some dependencies (typically using Outputs) but I've run into a situation that I have never run into before...
How do I use a resource created in one nested stack (A) in another nested stack (B) when using DependsOn?
This question is a duplicate question but the answer does not fit because it doesn't actually resolve the issue I have, it takes a different approach based on that particular user's needs.
Here is the resource in nested stack A:
EndpointARestApi:
Type: AWS::ApiGateway::RestApi
Properties:
Body:
Fn::Transform:
Name: 'AWS::Include'
Parameters:
Location: !Join ['/', [ 's3:/', !Ref SharedBucketName, !Ref WorkspacePrefix, 'endpoint.yaml' ]]
And here is the DependsOn request in stack B:
EndpointUserPoolResourceServer:
Type: Custom::CognitoUserPoolResourceServer
DependsOn:
- EndpointARestApi
- CustomResource ## this resource is in the same stack and resolves properly
This occurs with one other resource I have in this stack so I am hoping that I can do this easily. If not, I believe I would have to refactor some more.
As suggested in comments I moved the DependsOn statement up to the primary CFN script in the resource requiring the dependency and made sure the dependency was on the other resource, not the nested resource, like this:
Primary
ResourceA
ResourceB
DependsOn: ResourceA
Which ends up looking like this in the CloudFormation script:
EndpointUserPoolResourceServer:
Type: "AWS::CloudFormation::Stack"
DependsOn:
- EndpointARestApiResource
Properties:
Parameters:
AppName: !Ref AppName
Environment: !Ref Environment
DeveloperPrefix: !Ref DeveloperPrefix
DeployPhase: !Ref DeployPhase

CloudFormation: Deleting an entire nested stack

I have a CloudFormation stack which is made up of 3 nested stacks:
Resources:
ParamsSetup:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: a-params.yaml
ResourcePrep:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: b-prep.yaml
Services:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: c-service.yaml
I realized the ResourcePrep nested stack was unnecessary, so I moved the only important resource in that stack into the Services stack and removed the stack from my main template:
Resources:
ParamsSetup:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: a-params.yaml
Services:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: c-service.yaml
Now I have a problem. CloudFormation updates fail because the resource in Services already belongs to ResourcePrep, but ResourcePrep shouldn't exist anymore.
I had expected that CloudFormation would be smart enough to delete the removed stack, but it isn't. The removed stack is still there, and I don't know how to get rid of it. Everything I've read says you should never delete a nested stack manually.
You have a couple options here, none of which are particularly elegant like what your hoping.
Delete out the stack and leave the resource you want commented out (or deleted) for the cloudformation update/rebuild. After successfully updating with the stack removed, readd the resource you wanted/uncomment.
If the resource needs to be persisted, add a deletion retain parameter onto the resource, run the update, then delete the entire stack. After update complete re-add/reassociate the existing resource with the stack of your choosing.
Create an identical resource in the stack of your choosing with a different name and delete the odd stack.

How pass output values between aws nested stacks in serverless?

Here is readme about serverless-plugin-nested-stacks plugin. It makes possible to include nested stacks into main one. But how to pass values between stacks? For example I create a resouce in one nested stack - how to path it arn to another stack (nested or main one)?
First you will need to export the resources from the corresponding nested stack like this:
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
...
Resources:
...
Outputs:
o1:
Description: ...
Value: <your_resource_arn>
Export:
Name: <your_export_name>
To import the resource in other stack, you will need to use the intrinsic function Fn::ImportValue, like this:
Fn::ImportValue: <your_export_name>
For more information check the AWS documentation

Ec2TagFilters in deployment group for ComputePlatform: Lambda

I'm trying to work my way through a Cloud Formation stack creation. The stack includes an AWS::CodeDeploy::Application using CodePlatform: Lambda. It also has an AWS::CodeDeploy::DeploymentGroup.
If I run create-stack without the deployment group present, everything seems to work. I can then go into the web UI, and add the deployment group by hand.
But if I describe the deployment group in the template, and run create-stack, the create of the deployment group fails, and the stack gets rolled back. The error message looks like:
For Lambda deployment group, ec2TagFilters can not be specified (Service: AmazonCodeDeploy; Status Code: 400; Error Code: InvalidEC2TagException; Request ID: c4347652-c755-11e8-b8f1-6f54b77ae7fe)
... but my template's description of the deployment group doesn't include Ec2TagFilters
Ran into the same thing. No reference to the parameter, still errors. Added a Null Ec2TagFilters parameter and no luck. Weirdly, I then added a Deployment Style parameter, tried again, and it succeeded. Here's the CFN I ended with:
TestSSHConnectivityCodeDeployGroup:
Type: AWS::CodeDeploy::DeploymentGroup
Condition: InPrimaryRegion
Properties:
ApplicationName: !Ref TestSSHConnectivityCodeDeployApplication
DeploymentGroupName: Lambda-TestSSHConnectivity
DeploymentConfigName: CodeDeployDefault.LambdaAllAtOnce
DeploymentStyle:
DeploymentOption: WITH_TRAFFIC_CONTROL
DeploymentType: BLUE_GREEN
ServiceRoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/AWS-CodeDeploy-Service
I had this error happening in only 1 of my stacks in us-west-2. It was only a gamma environment so I deleted the stack, re-created it and everything was fine.
That won't work for everyone, but it did work in my case.