0
votes

Is there a way to send the variables from the root stack down to the children, then let each child stack create each resource by using cross stack references?

I'm trying to use a root stack to pass down some variables to the child stacks like stackName, then each child stack will use the stackName to create its own resource (e.g. API Gateway, DynamoDB, etc.).

==> The goal is to create a whole app from a root stack, with each resource (which is created by a child stack) has the same prefix like this-app-, then for a resource like DynamoDB, the table name will be this-app-dynamodb-table. So if it's code, it'd be something like this:

function main(stackName) {
  createRoles(stackName);
  createAPIGateway(stackName);
  createDynamoDB(stackName);
}
function createRoles(appName) {
  let roleARN = `${appName}ARN`;
  // create some roles
}
// more functions
main('this-app'); // call the root-stack or the main function, pass in the name of the app as a parameter.

From AWS Docs here, it seems like the root stack still has all the Resources and use "Fn::ImportValue.

From this guide about nested stacks, it looks like if I just want to reference to another stack, I'll have to save the stack in an S3 bucket then use:

{
  "Type" : "AWS::CloudFormation::Stack",
  "Properties" : {
      "NotificationARNs" : [ String, ... ],
      "Parameters" : {Key : Value, ...},
      "Tags" : [ Tag, ... ],
      "TemplateURL" : String,
      "TimeoutInMinutes" : Integer
    }
}

I've looked at some answers online but they don't solve the problem, or maybe I'm looking at the problem from a wrong angle.

Update 15 May

I've added the templates to an S3 bucket.

There's one thing I don't understand:

If the child stack looks like a normal one, how does it take the variable? I thought it should look like this:

 "Resources": {
        "RootStack": {
            "Type": "AWS::CloudFormation::Stack",
            "Properties" : {
                "TemplateURL": "https://s3.amazonaws.com/BUCKET/RootStack.json",
                "DynamoDBTableName": { 
                    "Fn::GetAtt" : [ "RootStack", "TableName" ]
                }
            }
        },
        "DDBTable": {
            "Type": "AWS::DynamoDB::Table",
            "Properties": {
                "TableName": {
                    "Fn::GetAtt" : [ "RootStack", "DynamoDBTableName" ]
                },
                "AttributeDefinitions": [...

and the RootStack.json should look like this:

"Resources": {
        "Database": {
            "Type": "AWS::CloudFormation::Stack",
            "Properties": {
                "Parameters": {
                    "TableName": {
                        "Fn::Sub": "${AWS::StackName}-dynamodb-table"
                    }
                },
                "TemplateURL": "https://s3.amazonaws.com/BUCKET/DatabaseStack.json.json"
            }
        }
    },...

Do I understand it correctly?

1
Have you had a look at nested stacks? You have one parent stack, and that parent stack can kick off multiple child stacks - passing down variables from the parent to the child.WarrenG
Yes. The second link included above is about working with nested stack. I can't make it work because it seems like the root stack still has all the properties.Viet

1 Answers

1
votes

You can pass down the parameters from the parent stack like this:

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "NestedStack Example",
  "Parameters" : {
    "MyParameter1" : {
      "Type" : "String"
    },
    "MyParameter2" : {
      "Type" : "String"
    },
    "MyParameter3" : {
      "Type" : "String"
    }
  },
  "Resources" : {
    "ChildStack1": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "Parameters": {
          "My1stParemeter": { "Ref": "MyParameter1" },
          "My2ndParemeter": { "Ref": "MyParameter2"}
        },
        "TemplateURL": "https://s3-eu-west-1.amazonaws.com/template-bucket/mytemplate1.json"
      }
    },
    "ChildStack2": {
        "Type": "AWS::CloudFormation::Stack",
        "Properties": {
          "Parameters": {
            "My3rdParemeter": { "Ref": "MyParameter3" }
          },
          "TemplateURL": "https://s3-eu-west-1.amazonaws.com/template-bucket/mytemplate2.json"
        }
      }
  }
}

You can also pass down attributes from resources created in your parent stack to child stacks. For example if you created an instance in your parent stack called myinstance then you could have this in your nested stack resource:

"ChildStack1": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "Parameters": {
          "MyEC2PrivateIP": { "Fn::GetAtt" : [ "myinstance", "PrivateIp" ] }
        },
        "TemplateURL": "https://s3-eu-west-1.amazonaws.com/template-bucket/mytemplate1.json"
      }

Your child cloudformation template would look like a normal template, nothing special to do there - you just need to have the parameters you are "pulling" in from the parent listed as parameters as per normal.