How to use templating in Terraform to spin up Fabric resources
The Terraform provider for Microsoft Fabric provides a convenient way to spin up resources in Microsoft Fabric. For a lot of resources you can provide an item definition to set some extra configurations when spinning up the resource.
Example: Deploying a Mirrored Database
Consider deploying a mirrored database using Terraform. You want to include all necessary details directly in your Terraform code. According to the provider documentation, here’s an example configuration:
1
2
3
4
5
6
7
8
9
10
11
12
resource "fabric_mirrored_database" "example_definition_bootstrap" {
display_name = "example2"
description = "example with definition bootstrapping"
workspace_id = "00000000-0000-0000-0000-000000000000"
definition_update_enabled = false
format = "Default"
definition = {
"mirroring.json" = {
source = "${local.path}/mirroring.json.tmpl"
}
}
}
While this example is helpful, it lacks details on structuring the .tmpl file. The Microsoft Learn page provides some guidance on what to include in the definition. However, you might want to make this definition dynamic to adapt to different environments.
Dynamic definition implementation
Here’s how you can implement a dynamic definition for a mirrored Azure SQL database in Terraform, assuming you have already defined a workspace and a connection to the Azure SQL Database in Microsoft Fabric:
fabric.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
resource "fabric_mirrored_database" "mirror" {
display_name = "mirror${var.environment}"
workspace_id = fabric_workspace.workspace.id
definition_update_enabled = false
format = "Default"
definition = {
"mirroring.json" = {
source = "${local.path}/mirror.json.tmpl"
tokens = {
"mirror_connection_id" = var.mirror_connection_id
"db_name" = "dbname${var.environment}"
}
}
}
}
locals.tf
1
2
3
locals {
path = "${path.module}/templates"
}
variables.tf
1
2
3
4
5
6
7
8
9
variable "environment" {
type = string
description = "The name of the environment (dev, tst, prd, etc.)"
}
variable "mirror_connection_id" {
description = "SQL database connection id in Fabric"
type = string
}
templates/mirror.json.tmpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"properties": {
"source": {
"type": "AzureSqlDatabase",
"typeProperties": {
"connection": "",
"database": ""
}
},
"target": {
"type": "MountedRelationalDatabase",
"typeProperties": {
"defaultSchema": "dbo",
"format": "Delta"
}
},
"mountedTables": [
{
"source": {
"typeProperties": {
"schemaName": "schema1",
"tableName": "table1"
}
}
},
{
"source": {
"typeProperties": {
"schemaName": "schema1",
"tableName": "table2"
}
}
}
]
}
}
The folder structure should look something like this:
1
2
3
4
5
6
7
.
├── fabric.tf
├── locals.tf
├── provider.tf
├── templates
│ └── mirror.json.tmpl
└── variables.tf
In this setup, variables are injected into the template, allowing the correct resource to be deployed based on the specified environment.