Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. L’infrastructure as Code avec Terraform
  3. Écrire du code Terraform
Extrait - L’infrastructure as Code avec Terraform Déployez votre infrastructure sur le Cloud
Extraits du livre
L’infrastructure as Code avec Terraform Déployez votre infrastructure sur le Cloud Revenir à la page d'achat du livre

Écrire du code Terraform

Le langage déclaratif HCL

HCL, pour HashiCorp Configuration Language, est le langage dédié pour décrire les ressources manipulées par Terraform.

Ce langage se veut déclaratif. Plutôt que d’utiliser des commandes de manière séquentielle, comme « Créer une base de données » ou « Attacher une adresse IP », Terraform propose aux utilisateurs de décrire l’état de l’infrastructure souhaité.

Sa structure est proche de JSON ou YAML. Il est d’ailleurs possible d’écrire du code Terraform en JSON. Cependant, HCL est moins verbeux, et plus simple d’écriture que JSON.

Pour permettre aux utilisateurs de décrire leur infrastructure, Terraform propose deux types de blocs principaux. Les blocs resource permettent de décrire un objet de cloud ou d’API qui devra être créé et maintenu par Terraform. Une ressource sera par exemple une machine virtuelle ou une base de données sur un cloud public, un groupe Active Directory ou LDAP, un enregistrement DNS, etc.

Voici un exemple d’un bloc resource déclarant une base de données PostgreSQL sur le cloud public Scaleway :

resource "scaleway_rdb_instance" "main" { 
  name = "sw-db" 
  node_type = "DB-DEV-S" ...

Les fichiers .tf

Le code Terraform doit être écrit dans des fichiers dont l’extension est .tf. Voici un exemple d’arborescence de fichiers contenant du code Terraform :

. 
├── .gitignore 
├── main.tf 
├── outputs.tf 
├── provider.tf 
├── README.md 
└── variables.tf 

Ce code contient plusieurs fichiers en plus des fichiers .tf. Le fichier README.md est un fichier de documentation à destination des utilisateurs du code et des développeurs. Le fichier .gitignore est un fichier de configuration interprété par Git. Un exemple d’un tel fichier est décrit dans le chapitre Outils externes - .gitignore.

Les autres fichiers ont l’extension .tf et contiennent donc du code Terraform. Par convention, le fichier main.tf est considéré comme le point d’entrée du code. Le fichier provider.tf contient la configuration des providers (cf. section Le bloc provider de ce chapitre). Les fichiers variables.tf et outputs.tf sont consacrés aux blocs portant le même nom.

Voici un autre exemple d’arborescence de fichiers de code Terraform :

. 
├── .gitignore 
├── databases.tf 
├── instances.tf 
├── main.tf 
├── networks.tf 
├──...

Les blocs resource et data

1. Le bloc resource

Les blocs resource, qui permettent de créer et manipuler des objets avec Terraform, ont la structure suivante :

resource "<TYPE>" "<NOM>" { 
  <ARGUMENT> = <EXPRESSION> 
} 

Le mot-clé resource est suivi du <TYPE> qui correspond au type d’objet que l’on souhaite instancier. Ces types sont définis dans les providers Terraform de chaque service cloud. Par exemple, le provider Scaleway définit des ressources comme "scaleway_rdb_instance" ou "scaleway_container". Le provider AWS définit des ressources comme "aws_instance" ou "aws_vpc". Le provider OVH définit des ressources comme "ovh_domain_ zone" ou "ovh_cloud_project_database". Le "<NOM>" est celui que l’on souhaite donner à sa ressource dans le code Terraform. Ce nom sert à référencer la ressource par ailleurs. Attention à bien distinguer ce nom associé au code, au nom réel de l’objet qui sera créé sur le cloud, qui lui sera défini le plus souvent par un argument.

Les "<TYPE>" et "<NOM>" doivent bien être déclarés sous la forme de chaîne de caractères en utilisant les guillemets doubles : ". Le contenu du bloc...

Les blocs variable, locals et output

Terraform permet aussi de définir des entrées et sorties dans le code, pour rendre le code réutilisable. Les entrées sont définies par des blocs variable, et les sorties par des blocs output.

Pour rendre le code plus lisible, il est également possible de définir des variables locales, qui pourront être réutilisées dans l’ensemble du code et qui sont définies par un bloc locals.

1. Le bloc variable

Les blocs variable permettent d’introduire de la réutilisabilité dans le code Terraform. Le code pourra déclarer un ensemble de variables, avec une valeur par défaut si besoin. À l’exécution, l’utilisateur devra fournir la valeur pour chacune des variables n’ayant pas de valeur par défaut (cf. chapitre Architecture et CLI Terraform - Le workflow et les commandes principales).

Voici un exemple de code déclarant une variable. La variable est utilisée dans la déclaration d’une ressource :

variable "instance_type" { 
  description = "type de machine" 
  type = string 
  default = "DB-DEV-S" 
} 
 
resource "scaleway_rdb_instance" "main" { 
  node_type = var.instance_type 
  engine = "PostgreSQL-11" 
} 

Ces deux blocs devraient être dans des fichiers différents ! Les variables sont toujours déclarées dans un fichier nommé variables.tf. Mais certains exemples de cet ouvrage listeront des blocs variable et des blocs resource ensemble pour rendre la lecture des exemples plus cohérente.

Les définitions de variable...

Les expressions

Les expressions sont les éléments du langage que l’on peut utiliser dans le code Terraform. Elles permettent de faire référence à d’autres éléments de code, d’effectuer des calculs, d’appeler des fonctions, etc.

1. Les expressions simples

Les valeurs des arguments peuvent être des expressions simples, parfois aussi appelées constantes, scalaires ou littérales. Ces expressions peuvent être :

  • une chaîne de caractères, définie entre guillemets doubles : "yoda" ;

  • une valeur booléenne : true ou false ;

  • une valeur numérique : 12 ou 3.1415 ;

  • une liste ou un tuple d’éléments, définis entre crochets et séparés par des virgules : [ "Hello", "World" ], ou [ true, 42 ] ;

  • une map ou dictionnaire d’éléments, définie entre accolades et contenant des couples clé/valeur : { nom = "Luke", age = 19 }.

2. Les références

Les expressions peuvent aussi faire usage d’une référence à un attribut d’un bloc resource ou data, ou à une variable d’entrée ou locals.

Pour référencer un attribut de bloc resource, il faut utiliser la syntaxe <TYPE>.<NOM>.<ATTRIBUT>.

Similairement, pour référencer un attribut de bloc data, il faut utiliser la syntaxe data.<TYPE>.<NOM>.<ATTRIBUT>.

Pour référencer une variable d’entrée, il faut utiliser la syntaxe var.<NOM> et pour référencer une variable locale, il faut utiliser la syntaxe local.<NOM>.

Voici un exemple de code commenté faisant un usage complet des références de code :

variable "region" {} 
 
variable "bucket_name" {} 
 
variable "project_name" {} 
 
locals { 
  // a local can reference a variable 
  region = var.region 
  // a local can reference a data 
  project_id = data.scaleway_account_project.project.project_id 
} 
 
data "scaleway_account_project" "project" { 
  name = var.project_name 
} ...

Le bloc provider

Les providers sont les plug-ins Terraform, qui contiennent le code nécessaire pour interagir avec les API des services cloud. Les providers définissent des ressources et data qui peuvent alors être utilisées dans le code Terraform.

Les providers doivent être configurés de deux façons. La première consiste à déclarer dans le code Terraform les dépendances requises. Ces dépendances listent les providers utilisés dans le code, leur source et le numéro de version souhaité. Ces dépendances sont utilisées par la commande terraform init pour télécharger les providers.

La seconde configuration consiste à donner à chaque provider les éléments requis pour se connecter aux API du service cloud. Ces éléments sont souvent des clés d’accès, clés d’API, identifiants de projets, organisations ou namespaces en fonction des services.

1. Dépendances aux providers

Les dépendances aux providers sont déclarées par convention dans un fichier versions.tf, avec un bloc required_providers, lui-même contenu dans un bloc terraform :

terraform { 
  required_providers { 
    NAME = { 
      source = "SOURCE" 
      version...

Les commentaires

Les commentaires en HCL peuvent être définis de trois manières.

Les commentaires sur une seule ligne sont définis avec un caractère dièse # ou double barre oblique //. Les commentaires multilignes sont définis avec / et </emphasis>/.

Par convention, le dièse # est préféré pour les commentaires monoligne.

/* 
Un commentaire multiligne 
permet de préciser plus d'informations 
*/ 
resource "random_integer" "priority" { 
  # un exemple de commentaire mono-ligne 
  min = 1 
  max = 1000 // un autre exemple 
} 

Conventions de nommage

Terraform n’impose pas de convention de nommage particulière. Les noms de blocs resource, data, variable ou output doivent être des chaînes de caractères contenant des lettres, chiffres, underscores _ et tirets -.

Par convention, il est préférable de toujours privilégier l’utilisation de la convention dite Snake Case, avec uniquement des minuscules, et des underscores à la place des tirets.

Par exemple, privilégier le nom app_database au nom app-database.

L’utilisation des underscores _ a un effet bonus intéressant : ils facilitent le copier-coller. Un double clic sur le nom de la ressource le sélectionnera en entier. Ce n’est pas le cas si le nom contient des tirets -.

Cette convention est suivie par le langage, avec par exemple la directive for_each, qui sera vue dans le chapitre Concepts avancés de Terraform - for_each, et également par le nommage de l’ensemble des ressources, comme dans notre exemple, avec le nom de la ressource scaleway_rdb_instance.

Il est aussi recommandé de simplifier les noms des ressources, en n’incluant pas le type de la ressource dans son nom. Par exemple, pour une ressource de type aws_s3_bucket qui servirait à archiver des fichiers, le nom suivant est recommandé :

resource "aws_s3_bucket" "archive" {} 

Il faut éviter de nommer...

Conclusion

Ce chapitre a présenté la structure du langage support à Terraform : HCL (pour HashiCorp Configuration Language), l’organisation du code, les différents blocs disponibles. Vous maîtrisez désormais les bases du langage de Terraform et vous possédez les prérequis pour lire et écrire du code simple pour commencer !

Le chapitre suivant est un peu différent des précédents puisqu’il liste des exemples d’usage de Terraform sur différents services cloud, avec différents providers et des codes de complexités variées. Ces exemples illustrent l’étendue des possibles avec Terraform et montrent des cas d’usage réels. Ils mettent aussi en avant quelques-unes des fonctionnalités avancées du langage HCL, qui sont expliquées plus en détail dans le chapitre Concepts avancés de Terraform.

Tous ces exemples sont disponibles sur GitHub et GitLab. Ils peuvent être repris et adaptés, et peuvent aussi servir de point de départ pour développer votre propre infrastructure !