Maîtriser les Expressions Terraform
Mise à jour :
Dans l’univers de Terraform, les expressions transforment les configurations statiques en solutions dynamiques et automatisées. Elles permettent aux administrateurs systèmes DevOps d’effectuer des répétitions, de conditionner la création de ressources et de réaliser des calculs. Ces capacités rendent les infrastructures plus adaptables et réactives aux besoins spécifiques d’une entreprise.
Utiliser les Boucles dans Terraform
Les boucles dans
Terraform
simplifient la création et la gestion de multiples ressources. Trois méthodes
peuvent être utilisées : count
, for_each
et la compréhension de liste avec
for
.
La Boucle avec count
**
La directive count
est idéale pour créer un nombre défini d’instances d’une
ressource. Elle est souvent utilisée lorsque vous avez besoin de plusieurs
copies identiques d’une ressource, avec seulement de légères variations.
Prenons l’exemple de la création de plusieurs instances de serveurs dans un cloud :
Dans cet exemple, Terraform crée cinq instances EC2 identiques. Vous pouvez
accéder à chaque instance individuellement en utilisant
aws_instance.server[0]
, aws_instance.server[1]
, etc.
La Boucle avec for_each
for_each
est utilisé lorsque chaque ressource doit être configurée de manière
unique, basée sur un ensemble de données, comme une liste ou un map. Cela est
utile pour des configurations où chaque ressource a ses propres paramètres
spécifiques.
Par exemple, la création de sous-réseaux dans différents emplacements pourrait se faire comme suit :
Ici, var.subnets
est un map avec des zones de disponibilité comme clés et des
blocs CIDR comme valeurs. for_each
crée un sous-réseau pour chaque paire
clé-valeur dans ce map.
Les boucles for
Les boucles avec for
permet de transformer et de filtrer des listes et des
maps. Elle est idéale pour créer de nouvelles structures de données à partir de
données existantes.
Par exemple, pour transformer une liste d’identifiants en une liste de noms de serveurs :
Dans cet exemple, pour chaque id
dans var.instance_ids
, un nouveau nom de
serveur est généré et ajouté à la liste instance_names
.
Une autre moyen de simplifier son écriture fait appel à l’opérateur splat [*]
Supposons que vous ayez défini vos instances EC2 comme suit dans Terraform :
Ici, count
permet de créer 5 instances. Si vous voulez récupérer les adresses
IP de toutes ces instances, vous pouvez utiliser le splat operator de cette
manière :
Dans cet exemple, aws_instance.example
fait référence à toutes les instances
EC2 créées. Le [*]
est le splat operator, qui est utilisé pour itérer sur
chaque instance et récupérer l’attribut public_ip
. Ainsi,
aws_instance.example[*].public_ip
renvoie une liste des adresses IP publiques
de toutes les instances EC2 créées par cette ressource.
C’est un moyen efficace de gérer les données de multiples ressources sans avoir à écrire des boucles ou des références individuelles pour chaque ressource. Le splat operator simplifie le code et le rend plus lisible, surtout lorsque vous travaillez avec un grand nombre de ressources similaires.
Les blocs dynamiques
Les bloc dynamiques de Terraform permettent de créer des configurations répétables et modulables. Ils sont particulièrement utiles lorsque vous devez créer plusieurs blocs de configuration similaires avec seulement quelques variations. Utiliser des blocs dynamiques rend votre code Terraform plus propre, plus organisé et plus facile à maintenir.
Supposons que vous avez une liste de règles de sécurité que vous souhaitez appliquer à un groupe de sécurité AWS. Au lieu de déclarer chaque règle individuellement, vous pouvez utiliser un bloc dynamique pour les créer toutes à partir d’une liste structurée.
Avec les blocs dynamiques, vous pouvez simplifier cela. Voici comment cela peut être fait :
Dans cette configuration, la variable ingress_rules
est une liste d’objets,
chaque objet représentant une règle d’entrée pour le groupe de sécurité. Vous
pouvez facilement ajouter ou supprimer des règles en modifiant cette liste,
rendant la gestion des règles de sécurité plus flexible et modulaire.
dynamic "ingress"
indique qu’il s’agit d’un bloc dynamique pour les règles d’entrée (ingress
).for_each = var.ingress_rules
spécifie que le bloc dynamique doit itérer sur chaque élément de la variablevar.ingress_rules
.- Le bloc
content
définit la configuration pour chaque règle d’entrée, avec des attributs commefrom_port
,to_port
,protocol
etcidr_blocks
.
En utilisant des blocs dynamiques, vous pouvez donc gérer efficacement des configurations répétitives et complexes, rendant votre code Terraform plus lisible et facile à gérer.
Implémenter des Conditions avec Terraform
La gestion conditionnelle des ressources dans Terraform est indispensable
pour créer des configurations flexibles et adaptatives. Terraform permet
d’implémenter des conditions principalement à travers deux méthodes :
l’utilisation de la propriété count
pour créer conditionnellement des
ressources et l’utilisation des expressions conditionnelles avec l’opérateur
ternaire.
Création Conditionnelle avec count
La propriété count
peut être utilisée pour contrôler la création d’une
ressource en fonction d’une condition. Si la condition est remplie, la ressource
est créée ; sinon, elle ne l’est pas.
Imaginons que vous souhaitiez créer une instance de base de données seulement si un certain drapeau est activé :
Ici, var.create_db
est une variable booléenne. Si elle est vraie (true
),
count
devient 1 et la base de données est créée. Si elle est fausse
(false
), count
est 0 et la ressource n’est pas créée.
Expressions Conditionnelles avec l’Opérateur Ternaire
L’opérateur ternaire condition ? true_value : false_value
permet d’assigner
des valeurs à des propriétés de ressource en fonction d’une condition. C’est une
manière concise d’écrire des conditions simples.
Par exemple, supposons que vous vouliez attribuer une taille différente à une instance en fonction de l’environnement :
Dans cet exemple, si var.environment
est égal à "prod"
, l’instance sera de
type t2.large
. Sinon, elle sera de type t2.small
.
Voici la liste des opérateurs de comparaison :
==
: Égal à!=
: Différent de>
: Plus grand que<
: Moins grand que>=
: Plus grand ou égal à<=
: Moins grand ou égal à
Et les opérateurs logiques permettant de combiner plusieurs conditions :
&&
: ET logique||
: OU logique!
: NON logique (négation)
Voici un exemple de l’utilisation de conditions logiques dans Terraform pour gérer la création et la configuration de ressources en fonction de conditions spécifiques. Imaginons que vous souhaitiez créer une instance AWS EC2, mais le type et la configuration de cette instance doivent varier en fonction de l’environnement de déploiement (par exemple, “production” ou “développement”) et d’une condition supplémentaire comme la nécessité d’une instance à haute disponibilité.
-
Variables :
environment
: Une variable pour déterminer l’environnement (production ou développement).high_availability
: Une variable booléenne pour indiquer si une haute disponibilité est nécessaire.
-
Ressource AWS EC2 (
aws_instance
) :count
:- Si l’environnement est “production” (
prod
) et que la haute disponibilité (high_availability
) est requise, Terraform créera deux instances (pour la redondance). - Dans tous les autres cas, une seule instance sera créée.
- Si l’environnement est “production” (
instance_type
:- Utilise un type d’instance plus grand (
t2.large
) pour la production et un type plus petit (t2.micro
) pour le développement.
- Utilise un type d’instance plus grand (
ami
:- ID d’une Amazon Machine Image (AMI) spécifique, utilisé ici à titre d’exemple.
tags
:- Des tags pour identifier l’environnement et indiquer si la haute disponibilité est activée ou non.
Cet exemple montre comment les conditions logiques dans Terraform peuvent être utilisées pour créer des configurations dynamiques, en fonction des besoins et des spécificités de l’environnement de déploiement.
Effectuer des Calculs avec Terraform
Terraform permet également d’effectuer de calcul pour manipuler les données de configuration. Ces calculs se font principalement à travers l’utilisation d’opérateurs arithmétiques, de fonctions intégrées et de manipulations de chaînes de caractères.
Opérateurs Arithmétiques dans Terraform
Les opérateurs arithmétiques standards sont utilisés pour effectuer des calculs de base. Ces opérateurs sont utiles pour définir des valeurs dynamiques basées sur des calculs. En voici la liste :
+
: Addition-
: Soustraction*
: Multiplication/
: Division%
: Modulo (reste de la division)
Par exemple, pour ajuster la taille d’une ressource en fonction d’un facteur multiplicateur :
Dans cet exemple, total_size
sera égal à 30, résultant de la multiplication de
base_size
par factor
.
Utilisation des Fonctions Intégrées
Terraform offre une variété de fonctions intégrées pour effectuer des opérations complexes. Ces fonctions incluent la manipulation de chaînes de caractères, la gestion des listes et des maps, les calculs mathématiques et bien plus.
Par exemple, pour combiner des chaînes de caractères et des nombres :
Ici, server_name
pourrait être quelque chose comme "server-prod-13"
,
combinant une chaîne de caractères avec des valeurs calculées.
Manipulations de Chaînes de Caractères
Les manipulations de chaînes de caractères sont fréquemment utilisées dans les
configurations Terraform pour personnaliser les noms, les tags et d’autres
propriétés de ressources. Des fonctions telles que format
, replace
, ou
split
permettent de traiter et de formatter les chaînes de caractères de
manière dynamique.
Prenons l’exemple de la création d’un nom de ressource basé sur plusieurs variables :
Dans cet exemple, format
est utilisé pour créer un nom structuré et informatif
pour l’instance, basé sur l’environnement et la taille calculée.
Les différentes fonctions intégrées
Voici une listre des principales fonctions disponibles:
Fonctions Numériques
abs(number)
: Renvoie la valeur absolue d’un nombre.ceil(number)
: Arrondit un nombre à l’entier supérieur.floor(number)
: Arrondit un nombre à l’entier inférieur.log(number, base)
: Calcule le logarithme d’un nombre avec une base spécifique.max(...)
: Renvoie le plus grand nombre d’un ensemble de nombres.min(...)
: Renvoie le plus petit nombre d’un ensemble de nombres.pow(x, y)
: Calcule x élevé à la puissance de y.signum(number)
: Renvoie le signe d’un nombre.
Fonctions sur les Chaînes de Caractères
format(format, ...)
: Formate une chaîne de caractères selon un format spécifié.join(delimiter, list)
: Joint les éléments d’une liste en une chaîne, séparés par un délimiteur.lower(string)
: Convertit une chaîne en minuscules.upper(string)
: Convertit une chaîne en majuscules.replace(string, search, replace)
: Remplace une sous-chaîne par une autre.split(delimiter, string)
: Divise une chaîne en une liste de chaînes, séparées par un délimiteur.substr(string, offset, length)
: Renvoie une sous-chaîne d’une chaîne donnée.
Fonctions sur les Collections (Listes et Maps)
length(collection)
: Renvoie le nombre d’éléments dans une collection.list(...)
: Crée une liste à partir d’arguments.map(...)
: Crée un map à partir d’arguments.element(list, index)
: Renvoie l’élément à un index donné dans une liste.lookup(map, key, default)
: Renvoie la valeur d’une clé dans un map, ou une valeur par défaut.
Fonctions de Hachage et d’Encodage
base64encode(string)
: Encode une chaîne en Base64.base64decode(string)
: Décode une chaîne encodée en Base64.md5(string)
: Calcule le hachage MD5 d’une chaîne.sha256(string)
: Calcule le hachage SHA256 d’une chaîne.
Fonctions sur les Types de Données
tonumber(string)
: Convertit une chaîne en nombre.tostring(value)
: Convertit une valeur en chaîne de caractères.tobool(value)
: Convertit une valeur en booléen.
Fonctions Diverses
timestamp()
: Renvoie le timestamp actuel.uuid()
: Génère un identifiant unique universel (UUID).
Voici un exemple de configuration Terraform utilisant plusieurs fonctions intégrées pour gérer une infrastructure complexe. Imaginons que vous devez créer des sous-réseaux dans AWS et le nombre ainsi que la configuration de ces sous-réseaux dépendent des données fournies par l’utilisateur.
-
Variables :
regions
: Liste des régions AWS où les sous-réseaux doivent être créés.cidr_base
: Bloc CIDR de base pour les sous-réseaux.
-
Locals :
cidr_blocs
: Utilise la fonctioncidrsubnet
pour créer des blocs CIDR uniques pour chaque région.region_cidr_map
: Crée un map associant chaque région à son bloc CIDR correspondant, en utilisant les fonctionszipmap
etrange
.
-
Ressource AWS Subnet (
aws_subnet
) :- Utilise
for_each
pour itérer sur le mapregion_cidr_map
. - Définit les paramètres de chaque sous-réseau, y compris l’ID du VPC, le bloc CIDR et la zone de disponibilité.
- Les tags de chaque sous-réseau incluent un nom unique généré en utilisant
les fonctions
format
,substr
etmd5
pour créer une étiquette distinctive basée sur le nom de la région et une partie du hachage MD5 du bloc CIDR.
- Utilise
Cet exemple illustre comment combiner diverses fonctions intégrées de Terraform pour créer une configuration dynamique et flexible, capable de s’adapter à un ensemble varié d’entrées et de besoins spécifiques.
Swich Case (simulé)
Terraform ne dispose pas d’une structure de contrôle switch
ou case
comme
on peut la trouver dans de nombreux langages de programmation traditionnels.
Cependant, Terraform offre une fonction intégrée nommée lookup
qui peut
être utilisée pour obtenir un effet similaire dans certaines situations. De
plus, des expressions conditionnelles et la fonction map
peuvent être
combinées pour imiter le comportement d’un switch
.
Pour simuler un switch
, vous pouvez utiliser un map pour définir les
correspondances clé-valeur et ensuite utiliser lookup
ou une compréhension de
liste pour sélectionner la valeur en fonction d’une clé donnée. Voici un exemple
simple :
Exemple Simulant un Switch avec lookup
.
Dans cet exemple, local.instance_sizes
est un map qui associe chaque
environnement à une taille d’instance EC2. La fonction lookup
est ensuite
utilisée pour obtenir la taille de l’instance basée sur la valeur de la variable
environment
. Si la clé n’est pas trouvée dans le map, lookup
retournera la
valeur par défaut spécifiée, ici "t2.micro"
.
Cela permet une certaine flexibilité similaire à un switch
, permettant de
sélectionner des valeurs en fonction de clés définies dans un map.
Conclusion
À travers ce guide, nous avons exploré comment les expressions Terraform, notamment les boucles, les conditions et les calculs, peuvent être utilisées pour créer des configurations dynamiques.
En utilisant judicieusement les boucles avec count
, for_each
et la
compréhension de liste avec for
, vous pouvez gérer de manière efficace des
ensembles complexes de ressources. Les conditions, bien qu’elles n’offrent pas
de structure switch
native, peuvent être habilement simulées avec des
fonctions comme lookup
pour adapter vos configurations à différents contextes.
De plus, les calculs avec les opérateurs arithmétiques et les fonctions
intégrées permettent une manipulation fine des données, rendant vos
configurations encore plus puissantes.