Cours - le langage HCL

Chlorure d’hydrogène (HCl)
Section titled “Chlorure d’hydrogène (HCl)”Le chlorure d’hydrogène, de symbole chimique HCl, est un corps composé de chlore et d’hydrogène, incolore, toxique et hautement corrosif. Dans les conditions ambiantes de température et de pression, c’est un gaz qui forme des fumées blanches au contact de l’humidité. Ces fumées sont constituées d’acide chlorhydrique, solution ionique de chlorure d’hydrogène dans l’eau.
HashiCorp Configuration Language (HCL)
Section titled “HashiCorp Configuration Language (HCL)”Documentation :
- Générale : https://github.com/hashicorp/hcl
- Specs : https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md
- Specs agnostiques : https://github.com/hashicorp/hcl/blob/main/spec.md
- Terraform : https://developer.hashicorp.com/terraform/language/
Un langage intermédiaire entre représentation et exécution
Section titled “Un langage intermédiaire entre représentation et exécution”- Langage inventé par HashiCorp pour remplacer les langages (de sérialisation de données) utilisés généralement pour la configuration comme JSON et YAML. Ils sont en effet plus verbeux et moins pratiques .
- Équilibre entre la lisibilité humaine et machine
- Influencé par des tentatives antérieures sur le terrain, telles que la configuration libucl et Nginx.
- Compatible avec JSON, ce qui signifie que HCL peut être converti 1:1 en JSON et vice versa.
- Pensé pour être utilisé par des langages typés, en l’occurence Go
Exercice : Transcrire un json => HCL
Section titled “Exercice : Transcrire un json => HCL”{ "name": "Jason Ray", "profession": "Software Engineer", "age": 31, "address": { "city": "New York", "postalCode": 64780, "Country": "USA" }, "languages": ["Java", "Node.js", "JavaScript", "JSON"], "socialProfiles": [ { "name": "Twitter", "link": "https://twitter.com" }, { "name": "Facebook", "link": "https://www.facebook.com" } ]}## We can use comments !
"name" = "Jason Ray"
"profession" = "Software Engineer"
"age" = 31
"address" = { "city" = "New York"
"postalCode" = 64780
"Country" = "USA"}
"languages" = ["Java", "Node.js", "JavaScript", "JSON"]
"socialProfiles" = { "name" = "Twitter"
"link" = "https://twitter.com"}
"socialProfiles" = { "name" = "Facebook"
"link" = "https://www.facebook.com"}https://www.convertsimple.com/convert-json-to-hcl/
Les composants du langage Terraform
Section titled “Les composants du langage Terraform”Les attributs
Section titled “Les attributs”Paires nom/valeur associée à un corps.
Les noms d’attributs sont uniques dans un corps donné.
Les valeurs d’attribut sont fournies sous forme d’expressions.
$ cat terraform.tfvars
htoken = "ht8ZrixBqIdsuaQn"Les blocs
Section titled “Les blocs”Structure imbriquée qui a un nom de type, zéro ou plusieurs étiquettes de chaîne (par exemple, des identifiants) et un corps imbriqué.
En général leur contenu est défini par un schéma préalable qui contient :
- un schéma des attributs
- un schéma du bloc d’en-tête (header)
Ensemble, les éléments structurels créent une structure de données hiérarchique, avec des attributs destinés à représenter les propriétés directes d’un objet particulier dans l’application appelante, et des blocs destinés à représenter des objets enfants d’un objet particulier.
$ cat main.tf
variable "base_cidr_block" { description = "A /16 CIDR range definition, such as 10.1.0.0/16, that the VPC will use" type = string default = "10.1.0.0/16"}
resource "aws_vpc" "main" { cidr_block = var.base_cidr_block}Les structures résultantes sont multi dimensionnelles
dictionary "level_1" "level_2" { var = "value"}
En JSON :
{ "dictionary": { "level_1": { "level_2": { "var": "value" } } }}Le corps
Section titled “Le corps”Conteneur représentant un ensemble de zéro ou plusieurs attributs et un ensemble de zéro ou plusieurs blocs.
Les attributs des schémas sont typés, et le corps a un type “name” par exemple.
L’autre mode est un mode dynamique / sans schéma.
$ cat variables.tf## Copyright (c) HashiCorp, Inc.variable "region" { description = "AWS region" type = string default = "us-east-2"}Le fichier de configuration
Section titled “Le fichier de configuration”Généralement produit en lisant un fichier sur le disque et en l’analysant comme une syntaxe particulière.
Dans terraform, le fichier de configuration est souvent le résultat d’une concaténation de plusieurs fichiers.
C’est là une des forces du langage qui autorise
- une composition des fichiers
- une surcharge potentielle
Les expressions
Section titled “Les expressions”Les valeurs d’attribut sont représentées par des expressions.
Selon la syntaxe concrète utilisée, une expression peut n’être qu’une valeur littérale ou elle peut décrire un calcul en termes de valeurs littérales, de variables et de fonctions.
## Basic typesmy_absent = nullmy_bool = truemy_int = 1024my_number = 3.1415926535897932384626433832795028841971693993751058
## Strings and templatesmy_str = "Something blue"my_heredoc = <<-EOT A multiline string with indents EOTsome_string = "My int is ${my_int}"
## Lists and mapsmy_list = ["blue", "green"]some_color = my_list[0]my_map = {type = "apple", color = "red"}some_type = my_map["type"]On peut effectuer des opérations de transtypages sur les variables (ex 0 => “0”).
Le langage étant typé, il existe toute une complexité de situations qui sont rares dans l’usage courant de Terraform.
Les références
Section titled “Les références”L’usage de références est courant dans Terraform.
L’usage de référence est ce qu’on a vu plus haut, le référencement d’un objet configuré dans le scope d’exécution.
$ cat main.tf
variable "base_cidr_block" { description = "A /16 CIDR range definition, such as 10.1.0.0/16, that the VPC will use" type = string default = "10.1.0.0/16"}
resource "aws_vpc" "main" { cidr_block = var.base_cidr_block}Les fonctions
Section titled “Les fonctions”L’usage de fonctions rapprche HCL des langages de templating comme jinja2.
Il existe des dizaines de fonctions dans Terraform
$ terraform console> keys({a=1, c=2, d=3})[ "a", "c", "d",]Elles permettent de filtrer, transformer, augmenter, qualifier, et toutes autres manipulations utiles des données gérées dans le fichier de configuration.
Les opérateurs et les conditions
Section titled “Les opérateurs et les conditions”HCL utilise des les opérateurs pour les
- opérations arithmétiques
{ a = (1+2) } - opérations de comparaisons
1 >= 2 - opérations logiques
true == false || 1 == 1
HCL utilise aussi la structure ternaire conditionnelle
> { a = true ? 1 : 2 }Les boucles
Section titled “Les boucles”Une expression for permet d’itérer sur une structure pour générer une nouvelle structure.
> [for s in ["foo","bar"] : upper(s)]
> [for k,v in {apple:"red",kiwi:"green"} : "${k} + ${v}"]
> {for k,v in {apple:"red",kiwi:"green"} : v => k}
> {for k,v in {apple:"fruit",kiwi:"fruit"} : v => k... }Les expressions de type splat simplifient la syntaxe d’accès à des contenus de listes
> [{"count": 32},{"count": 64}][*].countUn exemple réaliste
Section titled “Un exemple réaliste”terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 1.0.4" } }}
variable "aws_region" {}
variable "base_cidr_block" { description = "A /16 CIDR range definition, such as 10.1.0.0/16, that the VPC will use" type = string default = "10.1.0.0/16"}
variable "availability_zones" { description = "A list of availability zones in which to create subnets" type = list(string) default = ["us-east-2","eu-west-3"]}
provider "aws" { region = var.aws_region}
resource "aws_vpc" "main" { # Referencing the base_cidr_block variable allows the network address # to be changed without modifying the configuration. cidr_block = var.base_cidr_block}
resource "aws_subnet" "az" { # Create one subnet for each given availability zone. count = length(var.availability_zones)
# For each subnet, use one of the specified availability zones. availability_zone = var.availability_zones[count.index]
# By referencing the aws_vpc.main object, Terraform knows that the subnet # must be created only after the VPC is created. vpc_id = aws_vpc.main.id
# Built-in functions and operators can be used for simple transformations of # values, such as computing a subnet address. Here we create a /20 prefix for # each subnet, using consecutive addresses for each availability zone, # such as 10.1.16.0/20 . cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 4, count.index+1)}On peut agir dans le terminal avec cette recette
$ cd TH-01-HCL$ terraform init$ terraform console> var.base_cidr_block"10.1.0.0/16"