Skip to main content
net10.0

High-level Terraform module loader, inspector, and code emitter for .NET. Load Terraform modules, inspect variables/outputs/resources, and generate module calls.

Published
Sep 30, 2026
18d ago
Total Downloads
2.2K
2,176

Install

dotnet add package TerraformDotnet --version 2.0.0-preview.2
ProductVersions
.NET
net10.0

README

TerraformDotnet

A .NET toolkit for working with Terraform — parse HCL, load modules, inspect variables, and generate Terraform code.

NuGet License: MIT Built with GitHub Copilot

Packages

Package Description
TerraformDotnet.Hcl High-performance HCLv2 parser and writer, AOT-compatible
TerraformDotnet Terraform module loader and code generator built on top of TerraformDotnet.Hcl

Quick Start — TerraformDotnet

Load a Terraform module, inspect its variables, and generate the calling code.

Install

dotnet add package TerraformDotnet

Load and inspect a module

using TerraformDotnet.Module;

var module = TerraformModule.LoadFromDirectory("/path/to/module");

Console.WriteLine($"Required variables: {module.RequiredVariables.Count}");
foreach (var v in module.RequiredVariables)
{
    Console.WriteLine($"  {v.Name}: {v.Type?.ToHcl() ?? "any"} — {v.Description}");
}

Console.WriteLine($"Optional variables: {module.OptionalVariables.Count}");
Console.WriteLine($"Outputs: {module.Outputs.Count}");
Console.WriteLine($"Resources: {module.Resources.Count}");
Console.WriteLine($"Module calls: {module.ModuleCalls.Count}");

Generate a module call

using TerraformDotnet.Emit;

var call = new ModuleCallBuilder("my-app", module)
    .Source("git::https://example.com/modules/app?ref=v1.0")
    .FillRequired(name => $"var.{name}")
    .SetLiteral("tier", "premium")
    .IncludeOptionalComments(true)
    .Build();

var emitter = new ModuleCallEmitter(call);
string hcl = emitter.EmitModuleBlock();
// module "my-app" {
//   source = "git::https://example.com/modules/app?ref=v1.0"
//
//   project = var.project
//   region  = var.region
//   labels  = var.labels
//   tier    = "premium"
//
//   # (Optional) Maximum instance count.
//   # max_count = var.max_count
// }

Generate multiple files at once

emitter.WriteTo("output/", new FileEmitterOptions
{
    ModuleFileName = "resources-app.tf",
    VariablesFileName = "variables-app.tf",
    InputFiles = new Dictionary<string, IDictionary<string, InputValue>>
    {
        ["input-dev.tfvars"] = new Dictionary<string, InputValue>
        {
            ["project"] = new InputValue("\"dev-app\"", "Development"),
            ["region"] = "\"eu-west-1\"",
        },
        ["input-prod.tfvars"] = new Dictionary<string, InputValue>
        {
            ["project"] = new InputValue("\"prod-app\"", "Production"),
            ["region"] = "\"eu-west-1\"",
        },
    },
});

Quick Start — TerraformDotnet.Hcl

Parse and write HCL at any level of abstraction.

Install

dotnet add package TerraformDotnet.Hcl

Parse HCL into an AST

using TerraformDotnet.Hcl.Nodes;

var hcl = """
    resource "aws_instance" "web" {
      ami           = "ami-0c55b159cbfafe1f0"
      instance_type = "t2.micro"

      tags = {
        Name = "HelloWorld"
      }
    }
    """u8;

HclFile file = HclFile.Load(hcl);

HclBlock block = file.Body.Blocks[0];
Console.WriteLine(block.Type);       // "resource"
Console.WriteLine(block.Labels[0]);  // "aws_instance"
Console.WriteLine(block.Labels[1]);  // "web"

Write HCL

using TerraformDotnet.Hcl.Writer;

var buffer = new ArrayBufferWriter<byte>();
using var writer = new Utf8HclWriter(buffer);

writer.WriteBlockStart("resource", "aws_s3_bucket", "data");
writer.WriteAttribute("bucket", "my-bucket");
writer.WriteBooleanAttribute("force_destroy", true);
writer.WriteBlockEnd();
writer.Flush();

string output = Encoding.UTF8.GetString(buffer.WrittenSpan);
// resource "aws_s3_bucket" "data" {
//   bucket        = "my-bucket"
//   force_destroy = true
// }

Round-trip (parse → modify → emit)

var hcl = "name = \"old\""u8;
HclFile file = HclFile.Load(hcl);

file.Body.Attributes[0].Value = new HclLiteralExpression("new");

var buffer = new ArrayBufferWriter<byte>();
using var writer = new Utf8HclWriter(buffer);
new HclFileEmitter(writer).Emit(file);
writer.Flush();
// Output: name = "new"

Architecture

Layer Namespace Description
Reader TerraformDotnet.Hcl.Reader ref struct tokenizer — zero-copy, pull-based
Nodes TerraformDotnet.Hcl.Nodes AST model with visitor pattern and DeepClone()
Writer TerraformDotnet.Hcl.Writer Forward-only writer producing terraform fmt output
Evaluation TerraformDotnet.Hcl.Evaluation Expression evaluator with pluggable function resolver
Module TerraformDotnet.Module Terraform module loader and model
Emit TerraformDotnet.Emit Module call builder and code emitter
Functions TerraformDotnet.Evaluation Terraform function library and type conversion
Validation TerraformDotnet.Validation Variable constraint extraction and validation evaluation

See docs/hcl.md and docs/terraformdotnet.md for detailed documentation.

See docs/architecture.md for internal design and architecture.

Building

dotnet build all.csproj

Testing

dotnet test all.csproj

Performance

TerraformDotnet.Hcl uses stack-first, zero-copy design:

  • Utf8HclReader is a ref struct operating on ReadOnlySpan<byte>
  • Token values reference slices of the original input — no allocations for most tokens
  • No LINQ, no reflection in any hot path
  • AOT-compatible (IsAotCompatible = true)

License

MIT

Changes from Previous Version

No structural changes between v1.4.0 and v2.0.0-preview.2.

Adoption Assessment

Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.

This version is marked prerelease. Validate its API and upgrade path before production use.Compatibility metadata lists 1 target framework; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.