How to reference Cloudformation Ressources in a new Cloudformation template? - amazon-web-services

I have two Cloudformation files and I want to reference already created Ressources from one template, in another template. For Example: In the first one I create an ECS Cluster. In the second one I want to reference this cluster and build a Service in it. How can I do it?

To do this you have to exporting stack output values from the first template. Presumably this would be ECS Cluster name and/or its arn:
MyCluster:
Type: AWS::ECS::Cluster
Properties:
#....
Outputs:
MyClusterName:
Value: !Ref MyCluster
Export:
Name: ECSClusterName
Then in the second template you would use ImportValue to reference the exported output:
MyESSService:
Type: AWS::ECS::Service
Properties:
Cluster: !ImportValue ECSClusterName

Related

Create EFS accesspoints for an existing EFS using CloudFormation

Is it possible to create accesspoints for an existing EFS through CloudFormation?
For example, in the CloudFormation template:
First reference the EFS by a parameter
FileSystemResource:
Type: 'AWS::EFS::FileSystem'
Properties:
FileSystemId: !Ref some_param
BackupPolicy:
Status: ENABLED
PerformanceMode: generalPurpose
Encrypted: true
ThroughputMode: bursting
Then reference the EFS to create the access point?
SomeAccessPoint:
Type: 'AWS::EFS::AccessPoint'
Properties:
FileSystemId: !Ref FileSystemResource
You have to import your existing filesystem into CloudFormation first, before you can do this.

Cloudformation stack with nested resources fails to create

I'm trying to define some common resources (specifically, a couple of IAM roles) that will be shared between two environments, via a nested stack. The first environment to use the nested stack's resources creates ok, but the second one fails when trying to run the nested stack. Am I not understanding something about how nested stacks work, or am I just doing something wrong?
My nested stack is defined as:
AWSTemplateFormatVersion: '2010-09-09'
Description: Defines common resources shared between environments.
Parameters:
ParentStage:
Type: String
Description: The Stage or environment name.
Default: ""
ParentVpcId:
Type: "AWS::EC2::VPC::Id"
Description: VpcId of your existing Virtual Private Cloud (VPC)
Default: ""
Resources:
LambdaFunctionSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Identifies Lamdba functions to VPC resources
GroupName: BBA-KTDO-SG-LambdaFunction
VpcId: !Ref ParentVpcId
RdsAccessSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allows Lambda functions access to RDS instances
GroupName: BBA-KTDO-SG-RDS
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref LambdaFunctionSG
VpcId: !Ref ParentVpcId
I've uploaded that YAML file to an S3 bucket, and I'm then trying to use it in two separate stack files (i.e. app_dev.yaml and app_prod.yaml) as:
Resources:
CommonResources:
Type: 'AWS::CloudFormation::Stack'
Properties:
TemplateURL: "https://my-buildbucket.s3-eu-west-1.amazonaws.com/common/common.yaml"
Parameters:
ParentStage: !Ref Stage
ParentVpcId: !Ref VpcId
And referring to its outputs as (e.g):
VpcConfig:
SecurityGroupIds:
- !GetAtt [ CommonResources, Outputs.LambdaFunctionSGId ]
The first environment creates fine, including the nested resources. When I try to run the second environment, it fails with error:
Embedded stack
arn:aws:cloudformation:eu-west-1:238165151424:stack/my-prod-stack-CommonResources-L94ZCIP0UD9W/f9d06dd0-994d-11eb-9802-02554f144c21
was not successfully created: The following resource(s) failed to
create: [LambdaExecuteRole, LambdaFunctionSG].
Is it not possible to share a single resource definition between two separate stacks like this, or have I just missed something in the implementation?
As #jasonwadsworth mentioned that's correct names of the stacks are always amended with a random string at the end AWS::CloudFormation::Stack check the return values. Use GetAtt to get the name of the stack and construct the output. How do I pass values between nested stacks within the same parent stack in AWS CloudFormation?
Plus use aws cloudformation package command for packaging the nested stacks, no need to manually upload them to s3 bucket.
someting like
aws cloudformation package \
--template-file /path_to_template/template.json \
--s3-bucket bucket-name \
--output-template-file packaged-template.json
Take a look on the cloudformation output exports as well in case you are curious Difference between an Output & an Export

AWS Cloudformation: Outputs ServiceName for Unnamed ECS Service

I create ECS stack via cloudformation. Everything works fine.
Due to a certain reason, I do not specify ServiceName for ECS service (Name: Service) in definition.
However, I want to have it in outputs, after Cloudformation creates the stack.
So for this purpose, I defined outputs like this:
Outputs:
ECSServiceName:
Description: Service Name I want to see
Value: !GetAtt Service.ServiceName
When I run update CF Stack, I receive an error from AWS:
Requested attribute ServiceName must be a readonly property in schema for AWS::ECS::Service
Does this mean that I cannot receive it in outputs, if it wasn't strictly specified before? Or I made a mistake somewhere in Outputs definition?
You have to export ECSServiceName from your template. Also the correct way to get ECS service name is !GetAtt Service.Name:
Outputs:
ECSServiceName:
Description: Service Name I want to see
Value: !GetAtt Service.Name
Export:
Name: ECSServiceName
Then, in other templates, you can use ImportValue to reference the exported output:
!ImportValue ECSClusterName

Default value AWS replace with pseudo parameter reference

I have a parameter in an aws cloudformation template
Parameters:
ExecRole:
Type: String
Description: Required. Lambda exec role ARN
Default: arn:aws:iam::123456789:role/lambdaExecRole
Assuming the 123456789 is the AcountId I want to use the pseudo parameter reference but I cannot do it, I try the followings without success
Default: arn:aws:iam::!Ref{AWS::AccountId}:role/exLambdaExecRole
Default: !Sub 'arn:aws:iam::${AWS::AccountId}:role/exLambdaExecRole'
In the last case is throwing me an error
Default member must be a string.
It seems like functions (ex. !Sub) are not supported in default values of Parameters.
Here's a workaround we're using.
We have a separate stack called Parameters which exports whatever parameters needed in other stacks. For instance:
Outputs:
VpcId:
Description: Id of the VPC.
Value: !Ref VpcId
Export:
Name: !Sub 'stk-${EnvType}-${EnvId}-VpcId'
In other stacks we simply import these exported values:
VpcId: !ImportValue
'Fn::Sub': 'stk-${EnvType}-${EnvId}-VpcId'
EnvType and EnvId are the same for all the stacks of one environment.
With roles you might want to do the following. Create a separate Roles template, implement your roles there and export their ARNs:
Outputs:
LambdaExecutionRoleArn:
Description: ARN of the execution role for the log-and-pass function.
Value: !GetAtt
- LambdaExecutionRole
- Arn
Export:
Name: !Sub 'stk-${EnvType}-${EnvId}-roles-LambdaExecutionRole-Arn'
Again, in other stack you could simply ImportValue:
Role: !ImportValue
'Fn::Sub': 'stk-${EnvType}-${EnvId}-roles-LogAndPassFunctionExecutionRole-Arn'
Assuming this will always be role, why can't you as a parameter ask for the nae to be passed in then use the Sub intrinsic function to replace in the Resources section of your CloudFormation template.
That way your arn:aws:iam::${AWS::AccountId}:role part of the arn would not need to be part of the parameter.

AWS/Cloudformation: How to export/import parameter value to another stack (YAML)

I have a simple question. I am testing export/import of values in cloud formation.
Question is: How to create resources based on linked conditions from another stack?
I think I should import the value from other stack, but don't know how....
This is my "export-test-stack"
AWSTemplateFormatVersion: '2010-09-09'
Description: Export
Parameters:
EnvType:
Description: How many Instances you want to deploy?
Default: two
Type: String
AllowedValues:
- two
- three
ConstraintDescription: must specify number of deployed Instances
Conditions:
Deploy3EC2: !Equals [ !Ref EnvType, three ]
Resources:
Ec2Instance1:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SecurityGroupIds:
- sg-5d011027
ImageId: ami-0b33d91d
Ec2Instance2:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SecurityGroupIds:
- sg-5d011027
ImageId: ami-0b33d91d
Ec2Instance3:
Type: AWS::EC2::Instance
Condition: Deploy3EC2
Properties:
InstanceType: t2.micro
SecurityGroupIds:
- sg-5d011027
ImageId: ami-0b33d91d
Outputs:
EC2Conditions:
Description: Number of deployed instances
Value: !Ref EnvType
Export:
Name: blablabla
This is my "import-test-stack"
AWSTemplateFormatVersion: '2010-09-09'
Description: Import
Resources:
Ec2Instance1:
Type: AWS::EC2::Instance
Properties:
InstanceType: t2.micro
SecurityGroupIds:
- sg-7309dd0a
ImageId: ami-70edb016
Ec2Instance2:
Type: AWS::EC2::Instance
Condition: ?????? <<<<<<<<<
Properties:
InstanceType: t2.micro
SecurityGroupIds:
- sg-7309dd0a
ImageId: ami-70edb016
It's about cross stack reference, so I want to deploy Ec2Instance2 in "import-test-stack" only if I choose to deploy three Instances in previous "export-test-stack". How to do this?
So if I choose to deploy three instances, I want to use condition in "import stack" to deploy another two instances, if I choose to deploy two, it will deploy only one instance in "import-stack"
I know how conditions working, but still not able to find the way, how to use in cross reference stacks.
I know it's stupid example, but I just wanted to test that on as simple template as possible.
You have two choices: continue with separated stacks or combine them to create a nested stack.
With nested stacks you can use outputs from one stack as inputs to another stack.
If you want to keep using separated stacks use Fn::ImportValue function to import output values exported from another stack.
The both angles have been covered in Exporting Stack Output Values page. Also, the cross-stack reference walkthrough might help you if you choose to use Fn::ImportValue.
This will get you to import the correct value:
Fn::ImportValue: EC2Conditions
You can also use rules. You can make the rule be based on the value of your output.
we cannot use import value here as cloudformation does not allow to use intrinsic values in the parameter. But there is an option of using SSM (AWS System Management parameter store ) parameters in AWS which allows us to use the parameter in stack B which is created in stack A
Please check the link below article from AWS knowledge center
https://aws.amazon.com/premiumsupport/knowledge-center/cloudformation-systems-manager-parameter/