Aller au contenu

Permettre l'adoption de Fabric grâce à Lemniscat (Partie 1)

cover

Dans ma société, je m'occupe, entre autres, de mettre à disposition de mes collègues des espaces Azure (des groupes de ressources) dans lesquels ils peuvent découvrir les différents services Azure, tester des configurations Azure, etc. Récemment, avec la sortie de Microsoft Fabric, j'ai constaté que j'avais de plus en plus de demandes pour mettre à disposition des espaces Azure avec Microsoft Fabric.

Le problème, c'est que dans ma société, nous avons un tenant dédié pour toutes ces expérimentations. Mes collègues sont donc invités sur ce tenant pour pouvoir accéder aux ressources Azure. Et pour le moment, Microsoft Fabric ne permet pas aux utilisateurs invités d'utiliser le service.

Je devais donc systématiquement leur créer un compte spécifique sur le tenant pour leur permettre de tester Microsoft Fabric. Cela me prenait du temps et je ne trouvais pas cela très pratique.

En parallèle, j'ai initié un nouveau framework open source nommé Lemniscat. Ce framework permet de créer et de maintenir des produits orientés DevOps. Pour faire simple, ce framework est une sorte de "Terraform de Terraform" qui permet de construire des produits qui prennent en compte les différents aspects d'une démarche DevOps, orientée d'un point de vue consommateur du service.

Revenons à notre cas de Microsoft Fabric. Ce service est super intéressant car il offre une expérience unifiée des métiers autour de la data, de l'ingestion à la restitution en passant par la transformation, le machine learning, etc. C'est un service qui permet de faire de la data engineering, de la data science, du BI, etc. Bref, c'est un service qui peut intéresser beaucoup de monde.

Mais en tant qu'utilisateur de ce service, j'ai besoin de quoi, finalement ?

  • D'une capacité Fabric que je peux instancier sur Azure.
  • D'un accès à cette capacité pour pouvoir l'utiliser.
  • D'un environnement de travail pour pouvoir utiliser cette capacité (le Workspace Fabric).
  • D'un dépôt git pour pouvoir stocker mes artefacts de travail (mes notebooks, par exemple).

Bref, pour offrir une expérience digne de ce nom à mes collègues, je dois leur mettre à disposition tout cela. Et c'est là que Lemniscat intervient.

Dans cet article, je vais vous montrer comment j'ai pu mettre en place une capacité Fabric sur Azure et donner les droits sur cette capacité à mes collègues en utilisant Lemniscat.

Note

Dans cet article, je ne vais pas entrer dans les détails de Lemniscat. Si vous souhaitez en savoir plus sur Lemniscat, je vous invite à consulter la documentation.

Utilisons terraform pour déployer une capacité Fabric

Parce que c'est simple et que c'est un outil que tout le monde connaît, j'ai décidé d'utiliser Terraform pour déployer une capacité Fabric sur Azure. Cependant, rapidement, je suis confronté à un problème : il n'existe pas encore de module Terraform pour déployer une capacité Fabric sur Azure. Heureusement, j'ai trouvé un exemple de terraform qui permet de le faire. Ce n'est pas idéal, car il est basé sur azapi, mais cela fera l'affaire pour le moment.

Dans cet exemple, je constate qu'il est prévu uniquement pour autoriser un seul administrateur par capacité Fabric. Or, désormais, il est possible de définir plusieurs administrateurs par capacité. Ce n'est pas grave, nous allons effectuer une petite modification pour permettre à plusieurs de mes collègues d'utiliser la même capacité Fabric.

main.tf

resource "azapi_resource" "fab_capacity" {
  type                      = "Microsoft.Fabric/capacities@2022-07-01-preview"
  name                      = var.basename
  parent_id                 = var.resource_group_id
  location                  = var.location
  schema_validation_enabled = false

  body = jsonencode({
    properties = {
      administration = {
        members = var.admins_email
      }
    }
    sku = {
      name = var.sku,
      tier = "Fabric"
    }
  })
  tags = var.tags
}

variables.tf

variable "location" {
  type        = string
  description = "Location of the resource group."
}

variable "tags" {
  type        = map(string)
  default     = {}
  description = "A mapping of tags which should be assigned to the deployed resource."
}

variable "sku" {
  type        = string
  default     = "F2"
  description = "SKU name"
}

variable "admins_email" {
  type        = list(string)
  description = "Fabric administrators email"
}

Ajoutons la création de nos comptes utilisateurs

Maintenant que nous avons notre capacité Fabric, il nous faut créer les comptes utilisateurs qui pourront l'utiliser.

Note

Pour le moment, Microsoft Fabric ne permet pas l'utilisation d'utilisateurs invités. Ainsi, les utilisateurs doivent être dans le tenant Azure pour pouvoir y accéder.

Il faut donc que je crée des comptes à la volée pour mes collègues. Encore une fois, je vais utiliser Terraform pour cela.

De plus, il est nécessaire que je génère un mot de passe temporaire pour chaque utilisateur. Pour ce faire, je vais utiliser un module Terraform qui me permettra de générer un mot de passe aléatoire.

resource "random_password" "password" {
  length             = var.length
  special            = var.special
  override_special   = var.overrideSpecial 
}

Une fois que j'ai généré le mot de passe, je vais créer un compte utilisateur pour chacun des utilisateurs.

resource "azuread_user" "account" {
  for_each              = { for u in var.users : u.login => u }
  user_principal_name   = "${each.key}.${var.FABRICNAME}@${var.domainName}"
  display_name          = each.value.name
  mail_nickname         = each.key
  force_password_change = true
  password              = module.adminPassword[each.key].password

  lifecycle {
    ignore_changes      = [usage_location]
  }
}

Lorsque l'on crée un compte utilisateur, il est nécessaire que l'utilisateur change son mot de passe à la première connexion. C'est pourquoi j'ai ajouté force_password_change = true.

Warning

Dès que notre utilisateur va se connecte à Fabric, l'attribut usage_location sera mis à jour. C'est pourquoi j'ai ajouté ignore_changes = [usage_location] dans le bloc lifecycle. En effet, cet attribut ne peut pas être remis à null (voir : https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/user#usage_location).

Donc, maintenant nous avons notre capacité Fabric et nos utilisateurs.

Cependant, si nous voulons offrir une expérience optimale à nos collègues, il nous faut également créer un environnement de travail pour eux (le Workspace Fabric) et un référentiel Git pour stocker leur travail.

Malheureusement, il n'existe pas de module Terraform et azapi ne pourra pas nous venir en aide. Nous devons trouver une autre solution.

C'est une constatation que j'ai faite à maintes reprises. Il y a des choses que l'on peut réaliser avec Terraform et d'autres non. C'est là que Lemniscat entre en jeu.

Lemniscat pour ochestrer tout cela

Lemniscat est un framework qui permet de créer et de maintenir des produits orientés DevOps. Il permet de concevoir des produits qui prennent en compte les différents aspects d'une démarche DevOps, orientée du point de vue du consommateur du service.

Lemniscat fonctionne à partir d'un manifeste qui décrit le produit. Ce manifeste décrit comment le produit doit être instancié, mais aussi comment il doit être détruit. Ce dernier point est particulièrement pratique dans mon cas. En effet, je souhaite permettre à mes collègues de découvrir Microsoft Fabric, mais je ne veux pas qu'ils laissent leur capacité indéfiniment active. Nous disposons tout de même d'un budget limité et il est important que le plus grand nombre de mes collègues puissent profiter d'Azure. Avec Lemniscat, je peux définir la procédure de destruction du produit.

Initialisation du manfest Lemniscat

Nous allons nous concentrer dans cet article sur la création de la capacité Fabric et des utilisateurs. Nous aborderons dans un prochain article la création du Workspace Fabric et du dépôt Git. Dans le framework Lemniscat, cela correspond à la capacité operate.

Voici le manifeste Lemniscat pour la capacité Fabric et les utilisateurs :

capabilities:
  code: null
  build: null
  test: null
  release: null
  deploy: null
  operate:
    solutions: 
    - solution: Azure
      tasks:
        <ici nous crérons les opérations permettant de créer les compte utilisateurs et la capacité Fabric>

requirements:
  - name: lemniscat.plugin.terraform
    version: 0.2.5
  - name: lemniscat.plugin.filetransform
    version: 0.2.1

Configuration du fichier Tfvars

J'utilise Backstage pour offrir une expérience optimale. J'ai donc créé un formulaire qui permet de demander une capacité Fabric. Je demande à mes collègues quelques informations :

  • Le nom de la capacité Fabric : appName
  • La puissance de la capacité Fabric : skuName
  • La liste des utilisateurs à créer et qui seront Administrateurs de la capacité Fabric : users
  • La durée de vie de la capacité Fabric : delayBeforeCleanUp

Ces paramètres vont être renseignés dans un fichier tfvars que j'utiliserai ensuite avec Terraform. Pour cela, je vais utiliser la tâche filetransform de Lemniscat pour compléter le fichier tfvars.

- task: filetransform
  displayName: 'Set tfvars'
  steps:
    - pre
    - pre-clean
  parameters:
    folderPath: ${{ product.tfVarsPath }}
    fileType: json
    targetFiles: "*.tfvars.json"

Une fois cette tâche exécutée, j'ai mon fichier tfvars prêt à être utilisé par Terraform. Par exemple :

{
  "appName": "myFabric",
  "skuName": "F2",
  "users": [
    {
      "name": "John Doe",
      "login": "john.doe",
    },
    {
      "name": "Jane Doe",
      "login": "jane.doe",
    }
  ],
  "delayBeforeCleanUp": "1h"
}

Création de la capacité Fabric et des utilisateurs

Pour créer la capacité Fabric et les utilisateurs, je vais utiliser le plugin terraform de Lemniscat. Pour initialiser Terraform, je vais utiliser l'action init.

- task: terraform
  displayName: 'Terraform init'
  steps:
    - pre
    - run
    - pre-clean
    - run-clean
  parameters:
    action: init
    tfPath: ${{ product.tfPath }}
    backend:
      backend_type: azurerm
      storage_account_name: ${{ nc.workspace.stName }}
      container_name: tfstates
      key: ${{ productInstanceName }}.${{ rgTags.product_name }}.tfstate

Ensuite, je vais utiliser l'action plan pour vérifier que tout est correct, et notamment vérifier que les paramètres d'entrée sont corrects.

- task: terraform
  displayName: 'Terraform plan'
  steps:
    - pre
  parameters:
    action: plan
    tfPath: ${{ product.tfPath }}
    tfVarFile: ${{ product.tfVarsPath }}/${{ product.tfVarsFile }}
    tfplanFile: ${{ product.tfPath }}/terrafom.tfplan

Enfin, je vais utiliser l'action apply pour déployer la capacité Fabric et les utilisateurs.

- task: terraform
  displayName: 'Terraform apply'
  steps:
    - run
  parameters:
    action: apply
    tfPath: ${{ product.tfPath }}
    tfplanFile: ${{ product.tfPath }}/terrafom.tfplan

Destruction de la capacité Fabric et des utilisateurs

Une fois que la capacité Fabric et les utilisateurs ont été créés, il faut penser à les détruire (je rappelle que mes collègues ont besoin temporairement de cette capacité Fabric). Pour cela, je vais utiliser l'action destroy du plugin terraform.

- task: terraform
  displayName: 'Terraform destroy'
  steps:
    - run-clean
  parameters:
    action: destroy
    tfPath: ${{ product.tfPath }}
    tfVarFile: ${{ product.tfVarsPath }}/${{ product.tfVarsFile }}

Conclusion

Forcément, vous allez me dire que je me complique la vie. J'aurais tout simplement pu utiliser Terraform pour tout faire. Et vous avez raison.

Mais comme je l'indiquais au début de cet article, j'ai aussi besoin de créer un environnement de travail (le Workspace Fabric) et un dépôt Git.

Dans le prochain article, je vous montrerai comment avec Lemniscat j'ai pu créer un environnement de travail et un dépôt Git pour permettre à mes collègues conserver leur travail.

À suivre...

Références

Rédigé par Philippe MORISSEAU, Publié le 30 Mars 2024.