Skip to main content

Outputs and Exports


Introduction

Outputs let you expose important values from your stack. Exports let you share those values with other stacks.


Outputs

Basic syntax

Outputs:
OutputName:
Description: Description de l'output
Value: ValeurOuRéférence
Condition: ConditionName # Optionnel
Export: # Optionnel
Name: ExportName

Simple examples

Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16

MyInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t3.micro
ImageId: ami-12345678

Outputs:
# Output simple avec !Ref
VPCId:
Description: ID du VPC créé
Value: !Ref MyVPC

# Output avec !GetAtt
InstancePublicIP:
Description: IP publique de l'instance
Value: !GetAtt MyInstance.PublicIp

# Output avec !Sub
InstanceURL:
Description: URL de l'application
Value: !Sub 'http://${MyInstance.PublicDnsName}:8080'

# Output conditionnel
DatabaseEndpoint:
Condition: CreateDatabase
Description: Endpoint de la base de données
Value: !GetAtt Database.Endpoint.Address

Multi-value outputs

Outputs:
# Liste en chaîne
SubnetIds:
Description: IDs des subnets
Value: !Join
- ','
- - !Ref Subnet1
- !Ref Subnet2
- !Ref Subnet3

# JSON pour structures complexes
StackInfo:
Description: Informations de la stack
Value: !Sub |
{
"stackName": "${AWS::StackName}",
"region": "${AWS::Region}",
"vpcId": "${VPC}",
"environment": "${Environment}"
}

Exports (Cross-Stack References)

Exports let you share values between stacks.

Create an export

# Stack: network-stack
Outputs:
VPCId:
Description: ID du VPC
Value: !Ref VPC
Export:
Name: !Sub '${AWS::StackName}-VPCId'

PublicSubnetIds:
Description: IDs des subnets publics
Value: !Join [',', [!Ref PublicSubnet1, !Ref PublicSubnet2]]
Export:
Name: !Sub '${AWS::StackName}-PublicSubnets'

PrivateSubnetIds:
Description: IDs des subnets privés
Value: !Join [',', [!Ref PrivateSubnet1, !Ref PrivateSubnet2]]
Export:
Name: !Sub '${AWS::StackName}-PrivateSubnets'

Import a value

# Stack: application-stack
Resources:
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Subnets: !Split
- ','
- !ImportValue network-stack-PublicSubnets
SecurityGroups:
- !Ref ALBSecurityGroup

AppSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !ImportValue network-stack-VPCId
GroupDescription: Security group for application

ImportValue syntax

# Forme longue
Value: !ImportValue
Fn::Sub: '${NetworkStackName}-VPCId'

# Forme courte avec nom fixe
Value: !ImportValue network-stack-VPCId

# Avec Sub pour nom dynamique
Value: !ImportValue
!Sub '${NetworkStackName}-VPCId'

Pattern: Network Stack + Application

Network Stack (parent)

AWSTemplateFormatVersion: '2010-09-09'
Description: Stack réseau partagée

Parameters:
Environment:
Type: String
Default: dev

Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-vpc'

PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true

PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: !Select [1, !GetAZs '']
MapPublicIpOnLaunch: true

PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.11.0/24
AvailabilityZone: !Select [0, !GetAZs '']

PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.12.0/24
AvailabilityZone: !Select [1, !GetAZs '']

Outputs:
VPCId:
Description: VPC ID
Value: !Ref VPC
Export:
Name: !Sub '${AWS::StackName}-VPCId'

VPCCidr:
Description: VPC CIDR
Value: !GetAtt VPC.CidrBlock
Export:
Name: !Sub '${AWS::StackName}-VPCCidr'

PublicSubnets:
Description: Public subnet IDs
Value: !Join [',', [!Ref PublicSubnet1, !Ref PublicSubnet2]]
Export:
Name: !Sub '${AWS::StackName}-PublicSubnets'

PrivateSubnets:
Description: Private subnet IDs
Value: !Join [',', [!Ref PrivateSubnet1, !Ref PrivateSubnet2]]
Export:
Name: !Sub '${AWS::StackName}-PrivateSubnets'

AvailabilityZones:
Description: AZs utilisées
Value: !Join
- ','
- - !GetAtt PublicSubnet1.AvailabilityZone
- !GetAtt PublicSubnet2.AvailabilityZone
Export:
Name: !Sub '${AWS::StackName}-AZs'

Application Stack (consumer)

AWSTemplateFormatVersion: '2010-09-09'
Description: Stack application utilisant la stack réseau

Parameters:
NetworkStackName:
Type: String
Default: network-stack
Description: Nom de la stack réseau

InstanceType:
Type: String
Default: t3.micro

Resources:
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ALB Security Group
VpcId: !ImportValue
!Sub '${NetworkStackName}-VPCId'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0

AppSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Application Security Group
VpcId: !ImportValue
!Sub '${NetworkStackName}-VPCId'
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
SourceSecurityGroupId: !Ref ALBSecurityGroup

ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub '${AWS::StackName}-alb'
Subnets: !Split
- ','
- !ImportValue
!Sub '${NetworkStackName}-PublicSubnets'
SecurityGroups:
- !Ref ALBSecurityGroup
Type: application

TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: !Sub '${AWS::StackName}-tg'
Port: 8080
Protocol: HTTP
VpcId: !ImportValue
!Sub '${NetworkStackName}-VPCId'
HealthCheckPath: /health
TargetType: instance

AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
VPCZoneIdentifier: !Split
- ','
- !ImportValue
!Sub '${NetworkStackName}-PrivateSubnets'
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplate
Version: !GetAtt LaunchTemplate.LatestVersionNumber
MinSize: 2
MaxSize: 10
TargetGroupARNs:
- !Ref TargetGroup

LaunchTemplate:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
InstanceType: !Ref InstanceType
ImageId: !Sub '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2}}'
SecurityGroupIds:
- !Ref AppSecurityGroup

Outputs:
ALBEndpoint:
Description: URL de l'application
Value: !Sub 'http://${ApplicationLoadBalancer.DNSName}'

Listing exports

# Lister tous les exports
aws cloudformation list-exports

# Résultat
{
"Exports": [
{
"ExportingStackId": "arn:aws:cloudformation:...",
"Name": "network-stack-VPCId",
"Value": "vpc-12345678"
},
{
"ExportingStackId": "arn:aws:cloudformation:...",
"Name": "network-stack-PublicSubnets",
"Value": "subnet-1234,subnet-5678"
}
]
}

# Lister les imports d'un export
aws cloudformation list-imports \
--export-name network-stack-VPCId

Export constraints

Important rules

  1. Unique name: Export names must be unique within a region/account
  2. No deletion: You cannot delete a stack if its exports are in use
  3. No modification: You cannot modify an export that is in use
  4. Same region: Imports only work within the same region

Managing dependencies

# Vérifier qui utilise un export
aws cloudformation list-imports --export-name network-stack-VPCId

# Résultat
{
"Imports": [
"arn:aws:cloudformation:...:stack/app-stack-1/...",
"arn:aws:cloudformation:...:stack/app-stack-2/..."
]
}

Typical error

Export network-stack-VPCId cannot be deleted as it is in use by app-stack

Solution: First delete the stacks that import, then the stack that exports.


Best practices

1. Naming convention

# ✅ Bon - Préfixe avec le nom de la stack
Export:
Name: !Sub '${AWS::StackName}-VPCId'

# ✅ Bon - Inclure l'environnement
Export:
Name: !Sub '${Environment}-network-VPCId'

# ❌ Mauvais - Nom générique
Export:
Name: VPCId

2. Document exports

Outputs:
VPCId:
Description: |
ID du VPC principal.
Utilisé par: app-stack, database-stack
Format: vpc-xxxxxxxxx
Value: !Ref VPC
Export:
Name: !Sub '${AWS::StackName}-VPCId'

3. Use parameters for stack names

Parameters:
NetworkStackName:
Type: String
Description: Nom de la stack réseau à référencer

Resources:
MyResource:
Properties:
VpcId: !ImportValue
!Sub '${NetworkStackName}-VPCId'

Summary

ConceptDescription
OutputExposes a value from the stack
ExportMakes an output available to other stacks
ImportValueImports an export from another stack
ConditionMakes an output conditional

← Mappings and Conditions | Intrinsic Functions →