Utiliser le Pulumi Terraform Bridge - Partie 1 😍
L'infrastructure en tant que code (IaC) a transformé la gestion informatique, et Terraform d'HashiCorp a été un pilier dans ce domaine.
Mais que se passerait-il si vous pouviez combiner la puissance des providers de Terraform avec la flexibilité des langages de programmation populaires comme Python et JavaScript ?
C'est précisément ce que propose Pulumi et le Pulumi Terraform Bridge. 🙏
Vous avez été relativement nombreux/ses à vouloir un article sur ce sujet, c'est maintenant chose faite.
Avant de commencer, je souhaiterais préciser qu'il vous faudra quelques connaissances en Go pour y arriver sans trop de difficulté. 🫡
C'est parti, allons-y !
Récupération des prérequis 😄
Vous devez, avant de commencer avoir en votre possession :
- GNU Make (pour le Makefile)
- Golang (vers 1.18 ou supérieur)
- Goreleaser
- Git (obviously).
Et le "Terraform Bridge Provider Boilerplate" : https://github.com/pulumi/pulumi-tf-provider-boilerplate
Ce projet doit être forké chez vous, en respectant le format suivant :
pulumi-<provider_name>
Ce qui donne par exemple :
pulumi-maas
Ni plus, ni moins ! Ne reste plus qu'à cloner le repo chez vous :
git clone https://github.com/juhnny5/pulumi-maas.git
cd pulumi-maas/
Initialiser le repo
Le boilerplate, comme son nom l'indique fournit une base qu'il va falloir un peu adapter par rapport à notre provider à créer.
Pour ce faire, nous allons utiliser la commande suivante :
make prepare NAME=maas REPOSITORY=github.com/juhnny5/pulumi-maas
Cette commande va venir modifier les différents fichiers nécessaires au build et à la transformation, notamment le go.mod
par exemple.
Elle va également générer les ressources qui vont nous être utiles par la suite :
provider/cmd/pulumi-resource-maas
provider/cmd/pulumi-tfgen-maas
provider/resources.go
Cette commande modifie pas mal de choses, mais, dans mon cas, je vais chercher à convertir un provider qui n'est pas dans le repo officiel de Terraform. En effet, le provider de MaaS est sur le repo de l'orga du même nom, à savoir :
Ainsi, dans le fichier Makefile
, il me suffira de modifier les variables de cette sorte :
PROJECT_NAME := maas Package
SHELL := /bin/bash
PACK := maas
ORG := juhnny5
PROJECT := github.com/${ORG}/pulumi-${PACK}
NODE_MODULE_NAME := @juhnny5/${PACK}
TF_NAME := ${PACK}
PROVIDER_PATH := provider
VERSION_PATH := ${PROVIDER_PATH}/pkg/version.Version
TFGEN := pulumi-tfgen-${PACK}
PROVIDER := pulumi-resource-${PACK}
VERSION := $(shell pulumictl get version)
TESTPARALLELISM := 4
WORKING_DIR := $(shell pwd)
OS := $(shell uname)
EMPTY_TO_AVOID_SED := ""
Dans mon exemple, j'utilise un provider Terraform en source qui est un peu particulier. En effet, si on regarde le go.mod
du projet, celui-ci, on se rend compte que le nom du projet n'est pas le FQDN du projet sur GitHub mais simplement le nom du repo.
module terraform-provider-maas
go 1.19
require (
github.com/bflad/tfproviderlint v0.28.1
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/terraform-plugin-docs v0.16.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0
github.com/maas/gomaasclient v0.0.0-20230512141257-d73401ee0dc8
github.com/stretchr/testify v1.8.4
)
Ainsi, côté boilerplate, il faudra modifier notre go.mod
également pour que nous puissions utiliser cette lib en entrée. Ainsi donc :
vi provider/go.mod
On va remplacer le nom en spécifiant la version souhaitée. 🙃
module github.com/juhnny5/pulumi-maas/provider
go 1.19
replace (
github.com/hashicorp/terraform-plugin-sdk/v2 => github.com/pulumi/terraform-plugin-sdk/v2 v2.0.0-20230710100801-03a71d0fca3d
terraform-provider-maas v1.2.0 => github.com/maas/terraform-provider-maas v1.2.0
)
require (
github.com/pulumi/pulumi-terraform-bridge/v3 v3.57.0
github.com/pulumi/pulumi/sdk/v3 v3.76.1
terraform-provider-maas v1.2.0
)
Ainsi, nous pourrons utiliser le nom terraform-provider-maas
dans notre code. A noter que cette subtilité n'est pas toujours présente, cette manipulation est à réaliser dans le cas ou le provider source ne spécifie pas le FQDN Github dans son go.mod
.
Maintenant, il suffit de rajouter la dépendance vers ce provider Terraform dans notre fichier de resources. 🫡
Pour ce faire :
vi provider/resources.go
Et y ajouter terraform-provider-maas/maas
, de cette sorte :
package maas
import (
"fmt"
"path/filepath"
"terraform-provider-maas/maas"
"github.com/juhnny5/pulumi-maas/provider/pkg/version"
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge"
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/tokens"
shim "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim"
shimv2 "github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfshim/sdk-v2"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
)
Un coup de tfgen 🥸
Pour continuer, il faut lancer la commande :
make tfgen
Modifier les infos du futur provider Pulumi 👀
Par défaut, lorsque vous avez fait initialisé le projet, le fichier resources.go
a ajouté plusieurs infos concernant le projet. 😋
Nous allons y modifier d'autres infos avant de générer les SDKs. Le nom du Publisher
:
Mais également la description et l'org Github si celle-ci n'a pas été correctement modifiée.
Description: "A Pulumi package for creating and managing Canonical Metal-As-A-Service (MAAS) resources.",
GitHubOrg: "juhnny5",
Repository: "https://github.com/juhnny5/pulumi-maas",
Keywords: []string{"pulumi", "maas", "category/cloud"},
Ensuite, nous allons spécifier la configuration de chaque SDK à générer. Quand je parle de chaque SDK, j'entends par chaque langage de programmation à supporter par votre provider. 😈
Ainsi, vous pouvez obtenir ce résultat :
JavaScript: &tfbridge.JavaScriptInfo{
// List any npm dependencies and their versions
Dependencies: map[string]string{
"@pulumi/pulumi": "^3.0.0",
},
DevDependencies: map[string]string{
"@types/node": "^10.0.0", // so we can access strongly typed node definitions.
"@types/mime": "^2.0.0",
},
// See the documentation for tfbridge.OverlayInfo for how to lay out this
// section, or refer to the AWS provider. Delete this section if there are
// no overlay files.
//Overlay: &tfbridge.OverlayInfo{},
},
Python: &tfbridge.PythonInfo{
// List any Python dependencies and their version ranges
PackageName: "pulumi-maas",
Requires: map[string]string{
"pulumi": ">=3.0.0,<4.0.0",
},
},
Golang: &tfbridge.GolangInfo{
ImportBasePath: filepath.Join(
fmt.Sprintf("github.com/juhnny5/pulumi-%[1]s/sdk/", mainPkg),
tfbridge.GetModuleMajorVersion(version.Version),
"go",
mainPkg,
),
GenerateResourceContainerTypes: true,
},
CSharp: &tfbridge.CSharpInfo{
PackageReferences: map[string]string{
"Pulumi": "3.*",
},
},
Générer le code ! ☺️
Maintenant que l'on est tout bon sur les dépendances et dans l'initialisation du projet, nous allons pouvoir transformer notre code Terraform en code Pulumi et générer les SDKs appropriés. 😄
make build_sdks
Vous retrouverez automatiquement le code des différents SDKS dans sdk/
.
Une fois que c'est fait, il ne reste plus qu'à release votre code sur Github, je ne vais pas expliquer comment fonctionne Goreleaser ici, par contre, je vous invite à créer votre fichier de cette sorte :
A noter que vous trouverez un exemple dans le dossier deploymen-templates/
. Vous y trouverez également le README expliquant comment release votre projet.
Pour terminer, vous trouverez tout le code disponible ici si vous souhaitez un exemple concret :
Vous l'aurez compris, plus d'excuse pour ne pas migrer vers Pulumi. Le prochain article traitera de comment publier ces différentes ressources (sdks). 🤭