Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Cloudformation: Conditionally create properties of resources

I know that it is possible via the use of Conditions to conditionally (what else?) create resources.

I am trying to find a way though to conditionally create properties of resources;

in my case I am creating several EC2 instances in a subnet with default public ip assignment = false.

Sometimes though for debugging purposes I want my instances to get public IPs.

Now I have to comment in/out the SG/Subnet and the NetworkInterfaces properties below (those do not go together)

  myEC2:     Type: AWS::EC2::Instance     Metadata:       Comment: My EC2 Instance       AWS::CloudFormation::Init:         config:           commands:             01_provision:               command:                 !Sub |                   sed -i "s/somestring/${somevar}/" /some/path/     CreationPolicy:       ResourceSignal:         Timeout: PT4M     Properties:       ImageId: !FindInMap [ MyAamiMap, 'myami', amiid ]       InstanceType: "t2.2xlarge"       # SubnetId: !Ref SBNDemo1       # SecurityGroupIds: [!Ref SGInternalDemo]       NetworkInterfaces:         - AssociatePublicIpAddress: "true"           DeviceIndex: "0"           GroupSet:             - Ref: "SGInternalDemo"           SubnetId:             Ref: "SBNDemo1"       UserData:         "Fn::Base64":           !Sub |             #!/bin/bash -xe             # Start cfn-init             /usr/local/bin/cfn-init -s ${AWS::StackId} -r myEC2 --region ${AWS::Region} || echo 'Failed to run cfn-init'             # All done so signal success             /usr/local/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource myEC2 --region ${AWS::Region} 

Any suggestions?

like image 335
pkaramol Avatar asked Dec 05 '18 12:12

pkaramol


2 Answers

This might be a little late, but I recently had a same question.

From AWS docs, you can use Fn::If to set properties accordingly.

The template will look like:

Properties:   ImageId: !FindInMap [ MyAamiMap, 'myami', amiid ]   InstanceType: "t2.2xlarge"   # SubnetId: !Ref SBNDemo1   # SecurityGroupIds: [!Ref SGInternalDemo]   NetworkInterfaces:     !If     - YourCondition     -        AssociatePublicIpAddress: "true"       DeviceIndex: "0"       GroupSet:         - Ref: "SGInternalDemo"       SubnetId:         Ref: "SBNDemo1"     - !Ref "AWS::NoValue" 

AWS::NoValue means there will be no NetworkInterfaces properties set.

like image 160
12 revs, 2 users 98% Avatar answered Sep 19 '22 08:09

12 revs, 2 users 98%


Perhaps I am misunderstanding but this sounds like a parameter use case rather than a condition use case. I say that because you do not say under what conditions you would like a public ip. Just "sometimes for debugging purposes" How would the template know that you are debugging? You have to tell it with a parameter.

check out the docs https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html

So you could have a public ip parameter and a subnet id parameter and pass in what you like at stack creation.

One way that conditions could be useful is to create a debug parameter that would toggle public/private ip and subnet. Is this what you were thinking of?

To use conditions on properties use the IF function

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-conditions.html

I suggest setting your public subnet to provide a public ip on launch, and of course ensuring your private subnet does not do that. Then just pass the subnet in as a parameter.

https://docs.aws.amazon.com/vpc/latest/userguide/vpc-ip-addressing.html#subnet-public-ip

like image 39
Michael West Avatar answered Sep 20 '22 08:09

Michael West