1. Introduction à Atlas

atlas

Atlas est un outil indépendant du langage, conçu spécifiquement pour la gestion et la migration des schémas de bases de données en utilisant les principes modernes de DevOps. Il offre deux options de flux de travail :

  • Déclaratif : Similaire à Terraform, Atlas compare l'état actuel de la base de données avec l'état souhaité défini à l'aide de HCL, SQL ou le schéma ORM. Sur la base de cette comparaison, il génère et exécute un plan de migration pour transitionner la base de données vers son état souhaité.
  • Versionné : Contrairement à d'autres outils, Atlas planifie automatiquement les migrations de schéma pour vous. Les utilisateurs peuvent décrire leur schéma de base de données souhaité en utilisant HCL, SQL ou leur ORM choisi, et avec Atlas, planifier, examiner et appliquer les migrations nécessaires à la base de données.

Un avantage clé d'Atlas est sa simplification de la complexité de la gestion de base de données, la rendant facile pour le contrôle de version, la collaboration et la mise en œuvre.

2. Installation d'Atlas

Avant d'utiliser Atlas pour gérer les versions de bases de données, nous devons l'installer. Voici les étapes d'installation pour différentes plateformes.

2.1 Installation macOS + Linux

Sur les systèmes macOS ou Linux, vous pouvez télécharger et installer la dernière version d'Atlas en utilisant la ligne de commande suivante :

curl -sSf https://atlasgo.sh | sh

Cette commande détectera automatiquement la version du système d'exploitation, téléchargera la version de construction appropriée et placera le fichier binaire d'Atlas dans le chemin exécutable.

2.2 Installation via Homebrew

Si vous utilisez macOS et avez déjà installé le gestionnaire de paquets Homebrew, l'installation d'Atlas est aussi simple que d'exécuter la commande :

brew install ariga/tap/atlas

Cela récupérera la dernière version d'Atlas depuis le référentiel Homebrew et l'installera.

2.3 Installation de Docker

Installer et exécuter Atlas via Docker est une méthode rapide et pratique, surtout pour des tests temporaires ou pour les utilisateurs qui préfèrent ne pas installer de logiciels supplémentaires sur leur système hôte.

Tout d'abord, tirez l'image Docker d'Atlas :

docker pull arigaio/atlas

Ensuite, vous pouvez exécuter une commande d'aide pour confirmer une installation réussie :

docker run --rm arigaio/atlas --help

Si le conteneur doit accéder au réseau hôte ou à des répertoires locaux, utilisez l'indicateur --net=host et montez les répertoires requis :

docker run --rm --net=host \
  -v $(pwd)/migrations:/migrations \
  arigaio/atlas migrate apply \
  --url "mysql://root:pass@:3306/test"

2.4 Installation Windows

Téléchargez le fichier binaire, https://release.ariga.io/atlas/atlas-windows-amd64-latest.exe, et ajoutez le chemin d'installation à la variable d'environnement PATH du système.

3. Exporter la structure de la table de base de données existante à l'aide d'Atlas

Atlas propose la commande atlas schema inspect, qui peut être utilisée pour exporter la structure d'une base de données existante. Cette commande prend en charge la lecture des descriptions de la base de données à partir de l'URL de la base de données et les génère sous trois formats différents : le format Atlas HCL par défaut, le format SQL et le format JSON. Dans ce guide, nous allons montrer comment utiliser les formats Atlas HCL et SQL, car le format JSON est généralement utilisé pour traiter la sortie avec jq.

Pour inspecter une instance MySQL locale en cours d'exécution et écrire la sortie dans un fichier nommé schema.hcl, utilisez la commande suivante :

atlas schema inspect -u "mysql://root:pass@localhost:3306/example" > schema.hcl

Ouvrez le fichier schema.hcl pour afficher la définition de la structure de la table Atlas décrivant la base de données (HCL est un format de configuration de structure de table indépendant de la base de données défini par Atlas). Par exemple, ce fichier contiendra le contenu suivant :

table "users" {
  schema = schema.example
  column "id" {
    null = false
    type = int
  }
  column "name" {
    null = true
    type = varchar(100)
  }
  primary_key {
    columns = [column.id]
  }
}

Ce bloc de code représente une structure de table avec des colonnes id et name. Le champ schema fait référence à la définition du modèle example défini ailleurs dans ce document. De plus, le sous-bloc primary_key spécifie la colonne id comme la clé primaire de la table. Atlas s'efforce de reproduire la syntaxe de la base de données sur laquelle il opère. Dans cet exemple, la colonne id a un type int, tandis que la colonne name a un type varchar(100).

De même, pour exporter une définition de modèle SQL de la base de données, vous pouvez utiliser la commande suivante :

atlas schema inspect -u "mysql://root:pass@localhost:3306/example" --format '{{ sql . }}' > schema.sql

Ouvrez le fichier schema.sql pour visualiser la description SQL de la base de données, contenant généralement des instructions CREATE TABLE.

Cette approche permet de comprendre facilement les détails de la structure de la table de la base de données existante et fournit une référence précise pour les migrations versionnées ultérieures.

4.1 Workflow Déclaratif

Le Workflow Déclaratif d'Atlas permet aux utilisateurs de définir de manière déclarative l'état final désiré de la base de données. Les utilisateurs n'ont qu'à décrire l'état final souhaité du schéma de la base de données, et l'outil Atlas générera et exécutera automatiquement des plans de migration pour faire passer en toute sécurité le schéma de la base de données de l'état actuel à cet état attendu.

Voici comment utiliser le Workflow Déclaratif pour définir et atteindre l'état désiré de la base de données :

4.1.1 Définition de la structure cible de la table

Tout d'abord, vous devez créer un fichier définissant la structure attendue de la base de données, qui peut être au format HCL, SQL ou ORM (Mapping Objet-Relationnel).

Prenons le format HCL comme exemple, définissons une nouvelle table blog_posts :

table "blog_posts" {
  schema = schema.example
  column "id" {
    null = false
    type = int
  }
  column "title" {
    null = true
    type = varchar(100)
  }
  column "body" {
    null = true
    type = text
  }
  column "author_id" {
    null = true
    type = int
  }
  primary_key {
    columns = [column.id]
  }
  foreign_key "author_fk" {
    columns     = [column.author_id]
    ref_columns = [table.users.column.id]
  }
}

Astuce : Le format de syntaxe HCL sera abordé dans une section ultérieure.

4.1.2 Exécution de la migration à l'aide de l'outil Atlas

Une fois la définition de la structure de la table de la base de données terminée, vous pouvez utiliser la commande schema apply d'Atlas pour exécuter la migration.

atlas schema apply \
  -u "mysql://root:pass@localhost:3306/example" \
  --to file://schema.hcl

Après avoir exécuté la commande ci-dessus, Atlas comparera le schéma de la base de données existant avec le schéma défini dans le fichier, générera un plan de migration et demandera à l'utilisateur de confirmer l'exécution. Une fois l'utilisateur aura confirmé le plan d'exécution, Atlas exécutera la migration sur la base de données et la mettra à jour à l'état désiré.

4.2 Workflow Versionné

Le workflow versionné est un autre mode d'utilisation pris en charge par Atlas, parfois appelé "migration basée sur les changements". Il est adapté aux scénarios où les modifications du schéma de base de données doivent être versionnées et examinées dans le processus d'examen de code.

Les étapes du workflow versionné incluent :

4.2.1 Calculer les différences

Avant de commencer la migration, il est nécessaire de comparer la structure actuelle de la base de données avec l'état souhaité et de déterminer les différences entre les deux. Cela peut être réalisé en exécutant la commande atlas migrate diff.

atlas migrate diff create_blog_posts \
  --dir "file://migrations" \
  --to "file://schema.hcl" \
  --dev-url "docker://mysql/8/example"

Le paramètre --dir spécifie l'URL du dossier de migration, par défaut file://migrations. Le paramètre --to spécifie l'URL de l'état souhaité (par exemple, la base de données de votre environnement de développement), et --dev-url fournit une URL pour une base de données de développement utilisée pour calculer les différences (notez que ce --dev-url doit spécifier une base de données vide qu'Atlas utilise pour calculer les différences).

Astuce : Si vous souhaitez générer des fichiers SQL, consultez la section précédente pour définir le format en utilisant le paramètre --format.

4.2.2 Appliquer les modifications de migration

Après que le calcul des différences est terminé, Atlas générera deux fichiers de migration enregistrés dans le dossier migrations. Par exemple, si le format sélectionné est SQL, les fichiers générés par la commande diff, tels que le fichier SQL suivant, contiennent les commandes de migration pour créer une nouvelle table :

-- créer la table "blog_posts"
CREATE TABLE `blog_posts` (
  `id` int NOT NULL,
  `title` varchar(100) DEFAULT NULL,
  `body` text DEFAULT NULL,
  `author_id` int NULL REFERENCES `users`(id),
  PRIMARY KEY (`id`)
);

Une fois que les fichiers de migration sont générés, vous pouvez utiliser des outils de contrôle de version (par exemple, Git) pour gérer ces modifications. Cette approche permet d'apporter de nombreuses modifications à la structure de table de la base de données dans l'environnement de développement et, lorsqu'il est temps de publier, de comparer l'environnement de développement et l'environnement UAT en utilisant les commandes d'Atlas pour générer des fichiers de migration de la structure de table de la base de données. Ces fichiers de migration peuvent ensuite être appliqués aux environnements UAT et de production pour mettre à niveau la base de données.

Ces deux flux de travail, Déclaratif et Versionné, offrent une flexibilité pour différents modes de développement et de déploiement, permettant aux équipes de choisir la méthode qui convient le mieux aux besoins de leur projet pour gérer les modifications de schéma de base de données.

5. Description du Format HCL

5.1 Introduction

HCL est un langage déclaratif utilisé pour décrire les définitions de la structure de table de base de données. Atlas utilise le format HCL pour écrire les schémas de base de données, offrant une structure riche pour décrire différents aspects de la base de données. L'avantage de HCL réside dans sa lisibilité, sa facilité de maintenance et la prise en charge de fonctionnalités telles que l'injection de variables et des annotations supplémentaires.

Astuce : Si votre projet doit s'adapter à plusieurs bases de données, décrire les structures de table de manière indépendante de la base de données en utilisant HCL peut être très pratique.

5.2 Objet schema

L'objet schema est utilisé pour décrire un schéma de base de données. En MySQL et SQLite, il représente la DATABASE, tandis qu'en PostgreSQL, il représente le SCHEMA. Un fichier HCL peut contenir un ou plusieurs objets schema.

schema "public" {
  comment = "Un commentaire de schéma"
}

schema "private" {}

5.3 Objet table

L'objet table est utilisé pour décrire une table dans une base de données SQL, y compris les colonnes, les index, les contraintes et diverses propriétés supplémentaires prises en charge par différents pilotes de base de données.

table "users" {
  schema = schema.public
  column "id" {
    type = int
  }
  column "name" {
    type = varchar(255)
  }
  column "manager_id" {
    type = int
  }
  primary_key {
    columns = [
      column.id
    ]
  }
  index "idx_name" {
    columns = [
      column.name
    ]
    unique = true
  }
  foreign_key "manager_fk" {
    columns     = [column.manager_id]
    ref_columns = [table.users.column.id]
    on_delete   = CASCADE
    on_update   = NO_ACTION
  }
}

5.4 Objet column

La column est une sous-ressource de table utilisée pour définir les colonnes dans la table.

column "name" {
  type = text
  null = false
}

column "age" {
  type = integer
  default = 42
}

column "active" {
  type = tinyint(1)
  default = true
}

5.5 Objet primary_key

Le primary_key est une sous-ressource de table qui définit la clé primaire de la table.

primary_key {
  columns = [column.id]
}

5.6 Objet foreign_key

Le foreign_key est une sous-ressource de table qui définit les colonnes faisant référence à des colonnes dans d'autres tables.

table "orders" {
  schema = schema.market
  // ...
  column "owner_id" {
    type = integer
  }
  foreign_key "owner_id" {
    columns     = [column.owner_id]
    ref_columns = [table.users.column.id]
    on_update   = NO_ACTION
    on_delete   = NO_ACTION
  }
}

5.7 Objet index

L'objet index représente un index sur la table.

index "idx_name" {
  columns = [
    column.name
  ]
  unique = true
}