3
votes

I created an AWS Cloudformation template and I'm having trouble getting over a circular dependency. I'm creating an EC2 instance and a load balancer, the load balancer depends on the EC2 instance because it references it in its Instances properties. Everything was working fine until I had to reference the load balancer's DNSName property inside the EC2 instance Init section.

"AppServer": {
  "Type": "AWS::EC2::Instance",
  "Metadata": {
    "AWS::CloudFormation::Init" : {
      "configSets" : {
        "Install" : [ "Install" ]
      },
       ...
       ...
       ...
      "Install" : {
        "commands" : {
           "update hostname rmi" : {
            "command" : { "Fn::Join" : [ "", [ "runuser -lm rlt -c \"/home/ec2-user/awscf/update-rmi.sh ", { "Fn::GetAtt" : [ "WebLoadBalancer", "DNSName" ] }, "\"" ] ] }
          },
         }

So the problem here is that the EC2 instance can't reference the load balancer because it hasn't been created and the load balancer can't be created first because it needs the EC2 instance ID so it can be associated to it.

I looked at WaitConditions as well as CreationPolicy but unless I'm misunderstanding the way they work I don't think that they will help me. Essentially what I need is to a) Create the EC2 instance but don't execute UserData until the LoadBalancer has been created or b) Create the LoadBalancer first and don't associate it with the EC2 instance, once the EC2 instance is created go back and update the LoadBalancer to associate it with the EC2 instance. Does anyone know if something like that is possible? Outside of creating the full stack then going back and updating it manually? Ideally I'd like this to happen on the single creation of the stack.

2
You can use AutoscalingGroup with Launch configuration to seperate ELB dependency on the EC2 instance.kavin
ELB's instances is not a required field. Why not remove it and have your script add itself to the ELB?tedder42
@tedder42 that's one of my initial thoughts but how would I do that? Is it possible to go back and modify the ELB in the same template after it has been created? I'm trying to stay away from having to modify the template after the stack is created.so cal cheesehead

2 Answers

0
votes

You could look into using the cfn-get-metadata helper script from within the EC2 instance to retrieve Stack::Resource information.

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-get-metadata.html

0
votes

You may need to add Ref with each resource logical name.

I got the same error (Circular Dependency ) when I had:

  UserData:
    Fn::Base64:
      !Sub  |
      #!/bin/bash -xe
      # ...
      echo "<h1>I amrunning on ASG ${MyAutoScalingGroup}</h1>

Adding Ref resolves it as following:

  UserData:
    Fn::Base64:
      !Sub  |
      #!/bin/bash -xe
      # ...
      echo "<h1>I amrunning on ASG ${!Ref MyAutoScalingGroup}</h1>

Note: I am using YAML since JSON is horrible with Cloudformation.