Skip to content
Notifications
Clear all

Has anyone tried the Bicep to Terraform conversion tool? Is the output usable?

3 Posts
3 Users
0 Reactions
3 Views
(@sre_tales_new)
Eminent Member
Joined: 3 months ago
Posts: 17
Topic starter   [#476]

Alright, let's set the stage. A few months back, my team was staring down a barrel: a sprawling Azure environment defined entirely in Bicep, about 150 modules deep. The push from leadership was to standardize on Terraform for a multi-cloud future. The prospect of a manual rewrite was... daunting. We estimated 6-8 months of pure refactoring effort. That's when we started looking at the **Bicep to Terraform conversion tool** from the Azure Terraform provider team.

We ran a pilot on a moderately complex hub network setup, about 2,000 lines of Bicep. The tool *does* produce a `.tf` file. The output is syntactically correct Terraform HCL. But "usable" straight out of the box? Not for production. Here's what we found:

* **It's a literal, low-level translation:** It converts Bicep to the AzureRM provider's lower-level resources, not to the newer, recommended `azapi` resources. For example, a Bicep `Microsoft.Web/sites/sourcecontrols@2022-03-01` resource becomes a `azurerm_app_service_source_control` block, which has a different lifecycle and feature set.
* **No state import:** The tool only converts code. It doesn't help you import existing state. You're left with the monumental task of writing `terraform import` commands for every resource, mapping the new Terraform resource addresses to your Azure GUIDs. For 150 modules, this is a non-starter without significant scripting.
* **Loss of modularity:** Our clean Bicep modules get flattened. The output is a single, monolithic Terraform file. You lose all your logical separation, which means you then have to manually refactor it back into modules anyway.
* **Parameter and variable handling is basic:** Bicep parameters become Terraform variables, but the tool doesn't set up a `terraform.tfvars` file or manage different environments. You're left to structure that yourself.

Here's a tiny snippet of what the output looks like for a simple storage account:

```hcl
# Generated from Bicep: resource sa 'Microsoft.Storage/storageAccounts@2021-09-01'
resource "azurerm_storage_account" "sa" {
name = "storagetest${var.suffix}"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "GRS"
min_tls_version = "TLS1_2"
}
```

It's fine, but it's just a starting point. Our final verdict was that the tool saved us about **15-20%** of the initial code translation grunt work. However, the remaining 80%—state import, module refactoring, testing against actual dependencies, and aligning with our Terraform standards (like using `azapi` for newer features)—was still a massive, manual undertaking.

In the end, we used the tool as a **reference**, not a code generator. We ran it to understand the Terraform equivalent of a complex Bicep resource, then wrote our own modules from scratch. The migration was "worth it" for the long-term multi-cloud strategy, but the tool itself was not a silver bullet. It just turned an 8-month nightmare into a 6.5-month one.

My advice? Use it for discovery and to get a skeleton. But budget for the real work: state migration and modular design. The output is a foundation, not a house.

Has anyone else taken a different approach? Did you find a way to automate the state import mapping?

-- sre_tales


-- sre_tales


   
Quote
(@k8s_cost_ninja)
Estimable Member
Joined: 5 months ago
Posts: 70
 

Your state import point is critical. Even if you get usable Terraform code, the state mismatch will break everything.

We attempted a similar move and found the cost mapping impossible. The tool creates entirely new Terraform resource addresses. Your existing Azure resources have unique IDs, but Terraform's state will treat them as new.

You're forced into a risky operation: write a custom script to map every Bicep resource ID to the new Terraform resource address, then run `terraform import` for each one. For 150 modules, that's thousands of individual imports. One mapping error and you'll have duplicate resources or destroy something on the next apply.

The tool saves time on syntax, but the state migration effort often outweighs it. You're still looking at months of work.


null


   
ReplyQuote
(@martech_trial_taker_new)
Trusted Member
Joined: 2 months ago
Posts: 33
 

Oh wow, that's a great detail about the resource mapping. I hadn't thought about the `azurerm_app_service_source_control` versus `azapi` gap. Makes total sense the translation would use the older provider models.

Did you find that this caused actual drift or just meant missing out on newer features? I'm wondering if the output locks you into an older Terraform AzureRM provider version to keep things stable.

The state import problem alone sounds like a dealbreaker for any real migration. Seems like the tool gives you a rough starting draft, but you still need a full rewrite pass for anything production-ready.



   
ReplyQuote