Terraform has a built-in command to generate a Graphviz digraph representing the output of terraform plan, but this output is pretty messy and can’t render in MermaidJS.

terraform graph > graph.dot

These steps should clean things up so your graphs can be used in Gitlab, your blog, anywhere that supports MermaidJS!

digraph {
	compound = "true"
	newrank = "true"
	subgraph "root" {
		"[root] google_compute_address.nextcloud (expand)" [label = "google_compute_address.nextcloud", shape = "box"]
		"[root] google_compute_firewall.iap-to-nextcloud (expand)" [label = "google_compute_firewall.iap-to-nextcloud", shape = "box"]
		"[root] google_compute_firewall.nextcloud-external (expand)" [label = "google_compute_firewall.nextcloud-external", shape = "box"]
		"[root] google_compute_firewall.nextcloud-internal (expand)" [label = "google_compute_firewall.nextcloud-internal", shape = "box"]
...

Remove all lines with label = " as they aren’t setting any useful aliases and won’t work in MermaidJS.

Remove the strings [root] , " (expand)", " (close)" & \" as they are added to every element and don’t serve a purpose. Presumably Hashicorp imagined this graph being interactive.

Convert -> to --> and remove all " & \", lastly remove the top config lines (that don’t have ->) and the closing } at the end of file.

Example command:

sed -ri '/label =/d; s|\[root\] ||g; s| \(expand\)||g; s| \(close\)||g; s|\\"||g; s|\"||g; s|\s+->\s+|-->|g; /\t+?}/d' graph.dot

MermaidJS supports many graph formats but the one I typically use, and the only one I’ve properly tested these instructions against, is Flow Chart . To use flowchart add a line to the top with either flowchart LR; for left-to-right or flowchart TD; for top-to-bottom.

flowchart TD; google_compute_address.nextcloud-->provider[registry.terraform.io/hashicorp/google] google_compute_firewall.iap-to-nextcloud-->google_compute_network.nextcloud google_compute_firewall.nextcloud-external-->google_compute_network.nextcloud google_compute_firewall.nextcloud-internal-->google_compute_network.nextcloud google_compute_global_address.nextcloud_ip_address-->google_compute_network.nextcloud google_compute_health_check.nextcloud-->provider[registry.terraform.io/hashicorp/google] google_compute_instance_group_manager.nextcloud-->google_compute_health_check.nextcloud google_compute_instance_group_manager.nextcloud-->google_compute_instance_template.nextcloud google_compute_instance_template.nextcloud-->google_compute_address.nextcloud google_compute_instance_template.nextcloud-->google_service_account.nextcloud google_compute_instance_template.nextcloud-->google_sql_database_instance.nextcloud google_compute_instance_template.nextcloud-->var.container_name google_compute_instance_template.nextcloud-->var.container_tag google_compute_instance_template.nextcloud-->var.objectstore google_compute_instance_template.nextcloud-->var.smtp google_compute_network.nextcloud-->provider[registry.terraform.io/hashicorp/google] google_monitoring_dashboard.nextcloud-overview-->provider[registry.terraform.io/hashicorp/google] google_project_service.project-->provider[registry.terraform.io/hashicorp/google] google_service_account.nextcloud-->provider[registry.terraform.io/hashicorp/google] google_service_networking_connection.nextcloud_vpc_connection-->google_compute_global_address.nextcloud_ip_address google_sql_database.nextcloud-->google_sql_database_instance.nextcloud google_sql_database_instance.nextcloud-->google_service_networking_connection.nextcloud_vpc_connection google_sql_database_instance.nextcloud-->var.prefix google_sql_database_instance.nextcloud-->var.sql google_sql_user.nextcloud-->google_sql_database_instance.nextcloud google_storage_bucket.nextcloud-data-->provider[registry.terraform.io/hashicorp/google] google_storage_bucket.nextcloud-data-->var.domain google_storage_bucket.nextcloud-data-->var.objectstore provider[registry.terraform.io/hashicorp/google]-->google_compute_firewall.iap-to-nextcloud provider[registry.terraform.io/hashicorp/google]-->google_compute_firewall.nextcloud-external provider[registry.terraform.io/hashicorp/google]-->google_compute_firewall.nextcloud-internal provider[registry.terraform.io/hashicorp/google]-->google_compute_instance_group_manager.nextcloud provider[registry.terraform.io/hashicorp/google]-->google_monitoring_dashboard.nextcloud-overview provider[registry.terraform.io/hashicorp/google]-->google_project_service.project provider[registry.terraform.io/hashicorp/google]-->google_sql_database.nextcloud provider[registry.terraform.io/hashicorp/google]-->google_sql_user.nextcloud provider[registry.terraform.io/hashicorp/google]-->google_storage_bucket.nextcloud-data provider[registry.terraform.io/hashicorp/google]-->var.gcp_project provider[registry.terraform.io/hashicorp/google]-->var.gcp_region provider[registry.terraform.io/hashicorp/google]-->var.gcp_zone root-->provider[registry.terraform.io/hashicorp/google] root-->var.label root-->var.machine_type root-->var.nextcloud_repo root-->var.redis

This can be further tidied up by getting rid of the root--> & provider[registry.terraform.io/hashicorp/google].

sed -ri '/provider\[registry\.terraform\.io\/hashicorp\/google\]/d; /root-->/d' graph.dot
flowchart TD; google_compute_firewall.iap-to-nextcloud-->google_compute_network.nextcloud google_compute_firewall.nextcloud-external-->google_compute_network.nextcloud google_compute_firewall.nextcloud-internal-->google_compute_network.nextcloud google_compute_global_address.nextcloud_ip_address-->google_compute_network.nextcloud google_compute_instance_group_manager.nextcloud-->google_compute_health_check.nextcloud google_compute_instance_group_manager.nextcloud-->google_compute_instance_template.nextcloud google_compute_instance_template.nextcloud-->google_compute_address.nextcloud google_compute_instance_template.nextcloud-->google_service_account.nextcloud google_compute_instance_template.nextcloud-->google_sql_database_instance.nextcloud google_compute_instance_template.nextcloud-->var.container_name google_compute_instance_template.nextcloud-->var.container_tag google_compute_instance_template.nextcloud-->var.objectstore google_compute_instance_template.nextcloud-->var.smtp google_service_networking_connection.nextcloud_vpc_connection-->google_compute_global_address.nextcloud_ip_address google_sql_database.nextcloud-->google_sql_database_instance.nextcloud google_sql_database_instance.nextcloud-->google_service_networking_connection.nextcloud_vpc_connection google_sql_database_instance.nextcloud-->var.prefix google_sql_database_instance.nextcloud-->var.sql google_sql_user.nextcloud-->google_sql_database_instance.nextcloud google_storage_bucket.nextcloud-data-->var.domain google_storage_bucket.nextcloud-data-->var.objectstore

I hope this can save you time with your next infrastructure diagram!

For those wanting to generate image files from mermaid, this can be achieved with mermaid-cli .