Creating two ALB with exception if value put in instance id then will create alb, but Not able to pass two instance id values in parameter section - aws-cloudformation

Please help me with the I'm using to create two ALB with the exception if a value is put in one of the parameters then will create an alb that has the instances id but if I pass two instances id in the parameter ELB1InstanceIds then it gave me an error:
Properties validation failed for resource HTTPTG1 with message: #/Targets/0/Id: expected type: String, found: JSONArray
earlier I was using parameter `Type: 'ListAWS::EC2::Instance::Id' but when i don't select any instance in ELB2InstanceIds then I got an error that it required a selected value then only stack can be run.
so I have created with the type string and passed an instance id, it is working with one instance id but not working when I specify two instances id in one of the parameters.
Parameters:
ELB1InstanceIds:
Type: String
Default: i-12345678
ELB2InstanceIds:
Type: String
Default: i-12345678
Conditions:
IsELB1InstanceIdsNotEmpty: !Not [!Equals [!Ref ELB1InstanceIds, "i-12345678"]]
IsELB2InstanceIdsNotEmpty: !Not [!Equals [!Ref ELB2InstanceIds, "i-12345678"]]
Resources:
HTTPTG1:
Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
Properties:
Targets:
- Id: !If
- IsELB1InstanceIdsNotEmpty
- - !Split [",", !Ref ELB1InstanceIds]
- !Ref 'AWS::NoValue'
HTTPTG2:
Type: 'AWS::ElasticLoadBalancingV2::TargetGroup'
Properties:
Targets:
- Id: !If
- IsELB2InstanceIdsNotEmpty
- - !Split [",", !Ref ELB2InstanceIds]
- !Ref 'AWS::NoValue'
earlier I was using two parameters ELB1InstanceIds, and ELB2InstanceIds with Type: 'List<AWS::EC2::Instance::Id>' but when I don't select any instance in ELB2InstanceIds then I got an error that it required a selected value then only stack can be run.

Related

CloudFormation TaskDefinition with two different entry points based on condition

I have to add taskdefintion entry based on condition. Below is the template i created.
Conditions
IsProdEnv: !Equals [ !Ref envtype, "prod" ]
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
ContainerDefinitions:
EntryPoint:
- !If [IsProdEnv, !Split [",", ["python3", "hello.py"]], "./script.sh"]
I'm getting
Template error: every Fn::Split object requires two parameters, (1) a string delimiter and (2) a string to be split or a function that returns a string to be split.
You have two strings instead of one: "python3" and "hello.py". You need to have one string, e.g. "python3, hello.py". How this string looks, depends on your use-case.

How to dynamically create Resource (UserPool) name by concatenating parameter value and string in AWS CloudFormation YAML template?

I am trying to create an AWS CloudFormation template using YAML. I add a UserPool resource as follows. The user pool name & id should be obtained via a parameter value i.e., if the value of parameter paramUserPoolName is 'Sample', then:
UserPoolName = Sample
UserPool Resource Name = SampleUserPool i.e., concatenated value of 'paramUserPoolName + UserPool'
Parameters:
paramUserPoolName:
Type: String
Resources:
<I need 'paramUserPoolName + UserPool' here >:
Type: 'AWS::Cognito::UserPool'
Properties: {
"UserPoolName": paramUserPoolName
}
How can I dynamically create a resource id in CloudFormation template?
PS:
The following worked:
Resources:
SampleUserPool:
Type: 'AWS::Cognito::UserPool'
Properties:
UserPoolName: !Sub ${paramUserPoolName}UserPool
Use !Sub for that. You can also use !Join, but !Sub is easier.
Parameters:
paramUserPoolName:
Type: String
Resources:
Type: 'AWS::Cognito::UserPool'
Properties:
UserPoolName: !Sub ${paramUserPoolName}UserPool

Cloudformation LaunchTemplate referencing IamInstanceProfile fails to create

I am trying to create a LaunchTemplate, which references an IamInstanceProfile, in my Cloudformation stack. Here is the code- i have omitted the irrelevant parts:
...
Resources:
ServerLaunchTemplate:
Type: 'AWS::EC2::LaunchTemplate'
Properties:
LaunchTemplateData:
InstanceType: !Ref InstanceType
SecurityGroups:
- !Ref SecGroup
IamInstanceProfile: !Ref ServerProfile
UserData:
...
ServerProfile:
Type: 'AWS::IAM::InstanceProfile'
Properties:
Path: /
Roles:
- !Ref ServerRole
...
The ServerProfile gets created successfully. However when the stack creation process reaches the step of creating the ServerLaunchTemplate, it fails with the error:
Property validation failure: [Value of property {/LaunchTemplateData/IamInstanceProfile} does not match type {Object}]
If i omit the reference to the IamInstanceProfile, the LaunchTemplate get created successfully.
According to the documentation and some examples this should work... Based on the error i understand, that the InstanceType field of the LaunchTemplate needs to reference an object, but "!Ref InstanceType" returns the resource id.
How can i fix this? How could i retrieve the object, that is presumably required by the "/LaunchTemplateData/IamInstanceProfile" field?
Thank you
Easy to miss in the docs: IamInstanceProfile requires an IamInstanceProfile Cloudformation object with the Arn of the referenced IamInstanceProfile being a property of it.
See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata.html#cfn-ec2-launchtemplate-launchtemplatedata-iaminstanceprofile and https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-iaminstanceprofile.html.
This should work:
PortalLaunchTemplate:
Type: 'AWS::EC2::LaunchTemplate'
Properties:
LaunchTemplateName: !Sub ${InstanceName}-launch-template
LaunchTemplateData:
ImageId: !Ref AmiId
...
IamInstanceProfile:
Arn: !GetAtt InstanceProfile.Arn
What worked for me was:
"IamInstanceProfile":{ "Arn":
{
"Fn::Sub":"arn:aws:iam::${AWS::AccountId}:instanceprofile/${name_of_Instance_profile}"
}
Presumably because it requires the "Arn" value as a string.

create an Output in Cloudformation Stack with Fn::Select

Is it possible to create an Output of a stack like that at all:
TargetGroupARN1Part:
Description: the final portion of the target group ARN
Value:
Fn::Select:
- 5
- Fn::Split:
- ":"
- !Ref WebTG
When I try it I get:
Template format error: Invalid outputs property : [Fn::Select]
merci A
This should be working, as it worked on my tests.
You could also try the short form, such as:
TargetGroupARN1Part:
Description: the final portion of the target group ARN
Value: !Select [5, !Split [':', !Ref WebTG]]

!ImportValue in Serverless Framework not working

I'm attempting to export a DynamoDb StreamArn from a stack created in CloudFormation, then reference the export using !ImportValue in the serverless.yml.
But I'm getting this error message:
unknown tag !<!ImportValue> in "/codebuild/output/src/serverless.yml"
The cloudformation and serverless.yml are defined as below. Any help appreciated.
StackA.yml
AWSTemplateFormatVersion: 2010-09-09
Description: Resources for the registration site
Resources:
ClientTable:
Type: AWS::DynamoDB::Table
DeletionPolicy: Retain
Properties:
TableName: client
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 2
WriteCapacityUnits: 2
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
Outputs:
ClientTableStreamArn:
Description: The ARN for My ClientTable Stream
Value: !GetAtt ClientTable.StreamArn
Export:
Name: my-client-table-stream-arn
serverless.yml
service: my-service
frameworkVersion: ">=1.1.0 <2.0.0"
provider:
name: aws
runtime: nodejs6.10
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:DescribeStream
- dynamodb:GetRecords
- dynamodb:GetShardIterator
- dynamodb:ListStreams
- dynamodb:GetItem
- dynamodb:PutItem
Resource: arn:aws:dynamodb:*:*:table/client
functions:
foo:
handler: foo.main
events:
- stream:
type: dynamodb
arn: !ImportValue my-client-table-stream-arn
batchSize: 1
Solved by using ${cf:stackName.outputKey}
I struggled with this as well, and what did trick for me was:
functions:
foo:
handler: foo.main
events:
- stream:
type: dynamodb
arn:
!ImportValue my-client-table-stream-arn
batchSize: 1
Note, that intrinsic functions ImportValue is on a new line and indented, otherwise the whole event is ignored when cloudformation-template-update-stack.json is generated.
It appears that you're using the !ImportValue shorthand for CloudFormation YAML. My understanding is that when CloudFormation parses the YAML, and !ImportValue actually aliases Fn::ImportValue. According to the Serverless Function documentation, it appears that they should support the Fn::ImportValue form of imports.
Based on the documentation for Fn::ImportValue, you should be able to reference the your export like
- stream:
type: dynamodb
arn: {"Fn::ImportValue": "my-client-table-stream-arn"}
batchSize: 1
Hope that helps solve your issue.
I couldn't find it clearly documented anywhere but what seemed to resolve the issue for me is:
For the Variables which need to be exposed/exported in outputs, they must have an "Export" property with a "Name" sub-property:
In serverless.ts
resources: {
Resources: resources["Resources"],
Outputs: {
// For eventbus
EventBusName: {
Export: {
Name: "${self:service}-${self:provider.stage}-UNIQUE_EVENTBUS_NAME",
},
Value: {
Ref: "UNIQUE_EVENTBUS_NAME",
},
},
// For something like sqs, or anything else, would be the same
IDVerifyQueueARN: {
Export: {
Name: "${self:service}-${self:provider.stage}-UNIQUE_SQS_NAME",
},
Value: { "Fn::GetAtt": ["UNIQUE_SQS_NAME", "Arn"] },
}
},
}
Once this is deployed you can check if the exports are present by running in the terminal (using your associated aws credentials):
aws cloudformation list-exports
Then there should be a Name property in a list:
{
"ExportingStackId": "***",
"Name": "${self:service}-${self:provider.stage}-UNIQUE_EVENTBUS_NAME", <-- same as given above (but will be populated with your service and stage)
"Value": "***"
}
And then if the above is successful, you can reference it with "Fn::ImportValue" like so, e.g.:
"Resource": {
"Fn::ImportValue": "${self:service}-${self:provider.stage}-UNIQUE_EVENTBUS_NAME", <-- same as given above (but will be populated with your service and stage)
}