Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Multiple Stacks #14

Open
benwaine opened this issue Apr 1, 2019 · 2 comments
Open

Using Multiple Stacks #14

benwaine opened this issue Apr 1, 2019 · 2 comments

Comments

@benwaine
Copy link

benwaine commented Apr 1, 2019

You might want to use this module without embedding it as a nested stack because you want to share the VPC stack with many other CloudFormation stacks.

Once the stack is created, you can use the stack name (in this case vpc) as the value for the VpcModule parameter in other cfn-modules.

These lines above from the VPC module README seem to imply that it's possible to create multiple stacks and feed the exports of one stack into the another.

I'm trying to do this with the idea that my vpc and alerting stacks will be referenced from multiple applications stacks.

After successfully creating the vpc and alerting stacks following the instructions in these docs, I attempt to create an application stack like so:

---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Stay Nimble API Application Stack'
Resources:

....

  Alb:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      Parameters:
        VpcModule: 'sn-vpc'
        AlertingModule: 'sn-alerting' # optional
        Scheme: 'internet-facing'
        IdleTimeoutInSeconds: '60' # optional
      TemplateURL: './node_modules/@cfn-modules/alb/module.yml'

...

I get the following error when creating the application stack:

Embedded stack arn:aws:cloudformation:eu-west-2:357864412476:stack/sn-api-Alb-1830BJ8NFPN8E/9a619a80-5477-11e9-b51c-0ad01a6c5eea was not successfully created: No export named sn-alerting-Arn found

Looking at the alerting stack, there are no exports.

> aws cloudformation describe-stacks --stack-name=sn-alerting

{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:eu-west-2:357864412476:stack/sn-alerting/aa3e3800-5472-11e9-bc38-06afee4bb078",
            "StackName": "sn-alerting",
            "ChangeSetId": "arn:aws:cloudformation:eu-west-2:357864412476:changeSet/awscli-cloudformation-package-deploy-1554118706/b49bfd6d-fa00-4760-af0c-c18dc88db238",
            "Description": "Stay Nimble Alerting Stack",
            "CreationTime": "2019-04-01T11:38:27.093Z",
            "LastUpdatedTime": "2019-04-01T11:38:32.419Z",
            "RollbackConfiguration": {},
            "StackStatus": "CREATE_COMPLETE",
            "DisableRollback": false,
            "NotificationARNs": [],
            "Capabilities": [
                "CAPABILITY_IAM"
            ],
            "Tags": [],
            "EnableTerminationProtection": false,
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}

Looking at the nested stack created by my alerting stack I see exports including the expected ARN.


> aws cloudformation describe-stacks --stack-name=sn-alerting-Alerting-1VKQQLE2KMQ26

{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:eu-west-2:357864412476:stack/sn-alerting-Alerting-1VKQQLE2KMQ26/b04d9470-5472-11e9-9aec-02d140453e24",
            "StackName": "sn-alerting-Alerting-1VKQQLE2KMQ26",
            "Description": "cfn-modules: Alerting",
            "Parameters": [
                {
                    "ParameterKey": "Email",
                    "ParameterValue": ""
                },
                {
                    "ParameterKey": "FallbackEmail",
                    "ParameterValue": ""
                },
                {
                    "ParameterKey": "HttpsEndpoint",
                    "ParameterValue": ""
                },
                {
                    "ParameterKey": "HttpEndpoint",
                    "ParameterValue": ""
                }
            ],
            "CreationTime": "2019-04-01T11:38:37.624Z",
            "RollbackConfiguration": {},
            "StackStatus": "CREATE_COMPLETE",
            "DisableRollback": true,
            "NotificationARNs": [],
            "Capabilities": [
                "CAPABILITY_IAM"
            ],
            "Outputs": [
                {
                    "OutputKey": "ModuleId",
                    "OutputValue": "alerting"
                },
                {
                    "OutputKey": "ModuleVersion",
                    "OutputValue": "1.0.1"
                },
                {
                    "OutputKey": "Arn",
                    "OutputValue": "arn:aws:sns:eu-west-2:357864412476:sn-alerting-Alerting-1VKQQLE2KMQ26-Topic-1JTN2NUAX7RAV",
                    "ExportName": "sn-alerting-Alerting-1VKQQLE2KMQ26-Arn"
                },
                {
                    "OutputKey": "StackName",
                    "OutputValue": "sn-alerting-Alerting-1VKQQLE2KMQ26"
                }
            ],
            "Tags": [],
            "EnableTerminationProtection": false,
            "ParentId": "arn:aws:cloudformation:eu-west-2:357864412476:stack/sn-alerting/aa3e3800-5472-11e9-bc38-06afee4bb078",
            "RootId": "arn:aws:cloudformation:eu-west-2:357864412476:stack/sn-alerting/aa3e3800-5472-11e9-bc38-06afee4bb078",
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}

Is the design pattern I'm attempting possible? Have I missed something in terms of how to identify the stack in "child stacks"?

@michaelwittig
Copy link
Contributor

Hi @benwaine your alerting stack seems to be named sn-alerting-Alerting-1VKQQLE2KMQ26 not sn-alerting. You can create a normal (not nested) CloudFormation stack based on cfn-modules/alerting, name it sn-alerting and your idea should work.

Let me know if this works for you.

@ambsw-technology
Copy link

We reuse modules like this by creating exports. For example, this AlertingModule is shared by all of our (dedicated-to-client) environments for our APEX application:

Resources:
  AlertingModule:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      Parameters:
        Email: 'team@org.com' # optional
        HttpEndpoint: 'http://org.com/webhook' # optional
        HttpsEndpoint: 'https://org.com/webhook' # optional
        FallbackEmail: 'user@org.net' # optional
      TemplateURL: './node_modules/@cfn-modules/alerting/module.yml'
Outputs:
  AlertingModule:
    Description: 'The stack name of the alerting module.'
    Value: !GetAtt 'AlertingModule.Outputs.StackName'
    Export:
      Name: 'APEX-AlertingModule'

This lets us import the template elsewhere without having any relation between the two files:

  AlbModule:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      Parameters:
        AlertingModule: !ImportValue 'APEX-AlertingModule'
        VpcModule: !GetAtt 'VpcModule.Outputs.StackName'
        Scheme: 'internal'
      TemplateURL: './node_modules/@cfn-modules/alb/module.yml'
Outputs:
  EnvironmentAlbModule:
    Description: 'Environment ALB module.'
    Value: !GetAtt 'AlbModule.Outputs.StackName'
    Export:
      Name: !Sub 'APEX-${Environment}-AlbModule'

This example also exports the ALB in a narrower namespace since it's specific to a single client. When we want to build on that client's ALB, you need to use a slightly more verbose import...

  NlbAlbForward443:
    Type: 'AWS::CloudFormation::Stack'
    Properties:
      Parameters:
        VpcModule: {'Fn::ImportValue': !Sub 'APEX-${Environment}-VpcModule'}
        AlbModule: {'Fn::ImportValue': !Sub 'APEX-${Environment}-AlbModule'}
        NlbModule: !GetAtt 'NlbModule.Outputs.StackName'
        KmsKeyModule: {'Fn::ImportValue': !Sub 'APEX-${Environment}-KmsKeyModule'}
        Port: '443'
      TemplateURL: './apex-env-network-port.yaml'

As you can see, the VPC is also client-specific. The NLB is defined inline (in this same file). This particular template implements the lambda-based forwarding logic from an AWS Blog post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants