Aller au contenu principal

Outputs et Exports


Introduction

Les Outputs permettent d'exposer des valeurs importantes de votre stack. Les Exports permettent de partager ces valeurs avec d'autres stacks.


Outputs

Syntaxe de base

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

Exemples simples

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

Outputs multiples valeurs

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)

Les exports permettent de partager des valeurs entre stacks.

Créer un 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'

Importer une valeur

# 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

Syntaxe ImportValue

# 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 : Stack Network + Application

Stack Network (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'

Stack Application (consommatrice)

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}'

Lister les 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

Contraintes des exports

Règles importantes

  1. Nom unique : Les noms d'export doivent être uniques dans une région/compte
  2. Pas de suppression : Impossible de supprimer une stack si ses exports sont utilisés
  3. Pas de modification : Impossible de modifier un export utilisé
  4. Même région : Les imports ne fonctionnent que dans la même région

Gérer les dépendances

# 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/..."
]
}

Erreur typique

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

Solution : Supprimer d'abord les stacks qui importent, puis la stack qui exporte.


Bonnes pratiques

1. Convention de nommage

# ✅ 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. Documenter les 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. Utiliser des paramètres pour les noms de stack

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

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

Résumé

ConceptDescription
OutputExpose une valeur de la stack
ExportRend un output disponible pour d'autres stacks
ImportValueImporte un export d'une autre stack
ConditionRend un output conditionnel

← Mappings et Conditions | Fonctions Intrinsèques →