Documentation
¶
Overview ¶
Package tfgen generates Terraform JSON configuration from Go.
You describe infrastructure with plain Go values. A Stack holds one Terraform configuration, to which you add resources, data sources, modules, providers, outputs, and variables. Stack.Write then serialises it to Terraform JSON that any Terraform-compatible CLI (Terraform or OpenTofu) can apply.
The providers subpackages offer optional, typed constructors for common providers.
Example ¶
Example builds a minimal stack using only the core API and writes it as Terraform JSON.
package main
import (
"bytes"
"fmt"
"github.com/ably/tfgen"
)
func main() {
stack := tfgen.NewStack("example")
file := &tfgen.Resource{
Type: "local_file",
Name: "hello",
Config: tfgen.Config{
"content": "hello, world",
"filename": "hello.txt",
},
}
stack.AddResource(file)
// Reference an attribute of the resource in an output.
stack.AddOutput(&tfgen.Output{
Name: "path",
Value: file.Ref("filename"),
})
var buf bytes.Buffer
if err := stack.Write(&buf); err != nil {
panic(err)
}
fmt.Print(buf.String())
}
Output: { "output": { "path": { "value": "${local_file.hello.filename}" } }, "resource": { "local_file": { "hello": { "content": "hello, world", "filename": "hello.txt" } } } }
Example (Ably) ¶
Example_ably provisions an Ably app with a namespace and an API key, wiring the child resources to the app via references.
package main
import (
"bytes"
"fmt"
"github.com/ably/tfgen"
"github.com/ably/tfgen/providers/ably"
)
func main() {
stack := tfgen.NewStack("ably")
block := &tfgen.TerraformBlock{RequiredVersion: ">= 1.9"}
block.AddRequiredProvider("ably", ably.ProviderVersion())
stack.SetTerraformBlock(block)
stack.AddProvider(ably.Provider())
app := ably.App("main", ably.AppOptions{TLSOnly: true})
stack.AddResource(app)
stack.AddResource(ably.Namespace("chat", ably.NamespaceOptions{
AppID: app.Ref("id"),
Persisted: true,
}))
stack.AddResource(ably.APIKey("publisher", ably.APIKeyOptions{
AppID: app.Ref("id"),
Capabilities: map[string][]string{"chat:*": {"publish", "subscribe"}},
}))
var buf bytes.Buffer
if err := stack.Write(&buf); err != nil {
panic(err)
}
fmt.Print(buf.String())
}
Output: { "provider": { "ably": {} }, "resource": { "ably_api_key": { "publisher": { "app_id": "${ably_app.main.id}", "capabilities": { "chat:*": [ "publish", "subscribe" ] }, "name": "publisher" } }, "ably_app": { "main": { "name": "main", "tls_only": true } }, "ably_namespace": { "chat": { "app_id": "${ably_app.main.id}", "id": "chat", "persisted": true } } }, "terraform": { "required_providers": { "ably": { "source": "ably/ably", "version": "1.0.0" } }, "required_version": ">= 1.9" } }
Example (Aws) ¶
Example_aws builds a stack using the AWS provider helpers.
package main
import (
"bytes"
"fmt"
"github.com/ably/tfgen"
"github.com/ably/tfgen/providers/aws"
)
func main() {
stack := tfgen.NewStack("aws")
block := &tfgen.TerraformBlock{RequiredVersion: ">= 1.9"}
block.AddRequiredProvider("aws", aws.ProviderVersion("~> 5.0"))
stack.SetTerraformBlock(block)
stack.AddProvider(aws.Provider("primary", "eu-west-1", tfgen.Config{
"managed_by": "tfgen",
}))
stack.AddResource(&tfgen.Resource{
Type: "aws_s3_bucket",
Name: "example",
Config: tfgen.Config{"bucket": "my-example-bucket"},
})
var buf bytes.Buffer
if err := stack.Write(&buf); err != nil {
panic(err)
}
fmt.Print(buf.String())
}
Output: { "provider": { "aws": { "alias": "primary", "default_tags": [ { "tags": { "managed_by": "tfgen" } } ], "region": "eu-west-1" } }, "resource": { "aws_s3_bucket": { "example": { "bucket": "my-example-bucket" } } }, "terraform": { "required_providers": { "aws": { "source": "hashicorp/aws", "version": "~> 5.0" } }, "required_version": ">= 1.9" } }
Example (Cloudflare) ¶
Example_cloudflare builds a stack using the Cloudflare provider helper.
package main
import (
"bytes"
"fmt"
"github.com/ably/tfgen"
"github.com/ably/tfgen/providers/cloudflare"
)
func main() {
stack := tfgen.NewStack("cloudflare")
block := &tfgen.TerraformBlock{RequiredVersion: ">= 1.9"}
block.AddRequiredProvider("cloudflare", cloudflare.ProviderVersion("~> 4.0"))
stack.SetTerraformBlock(block)
stack.AddProvider(cloudflare.Provider())
stack.AddResource(&tfgen.Resource{
Type: "cloudflare_record",
Name: "www",
Config: tfgen.Config{
"zone_id": "${var.zone_id}",
"name": "www",
"type": "CNAME",
"content": "example.com",
"proxied": true,
},
})
var buf bytes.Buffer
if err := stack.Write(&buf); err != nil {
panic(err)
}
fmt.Print(buf.String())
}
Output: { "provider": { "cloudflare": {} }, "resource": { "cloudflare_record": { "www": { "content": "example.com", "name": "www", "proxied": true, "type": "CNAME", "zone_id": "${var.zone_id}" } } }, "terraform": { "required_providers": { "cloudflare": { "source": "cloudflare/cloudflare", "version": "~> 4.0" } }, "required_version": ">= 1.9" } }
Index ¶
- func MarshalJSON(v any) ([]byte, error)
- func OutputFile(path string) (*os.File, error)
- func StackOutputWriter(baseDir, stackName string) (*os.File, error)
- type Backend
- type Config
- type Data
- type DataSources
- type Generator
- type Module
- type ModuleSource
- type Modules
- type Output
- type Outputs
- type Provider
- type ProviderRequirement
- type Providers
- type RequiredProviders
- type Resource
- type Resources
- type Stack
- func (s *Stack) AddData(data *Data)
- func (s *Stack) AddModule(module *Module)
- func (s *Stack) AddOutput(output *Output)
- func (s *Stack) AddProvider(provider *Provider)
- func (s *Stack) AddResource(resource *Resource)
- func (s *Stack) AddVariable(variable *Variable)
- func (s *Stack) JSON() ([]byte, error)
- func (s *Stack) SetData(data []*Data)
- func (s *Stack) SetModules(modules []*Module)
- func (s *Stack) SetOutputs(outputs []*Output)
- func (s *Stack) SetProviders(providers []*Provider)
- func (s *Stack) SetResources(resources []*Resource)
- func (s *Stack) SetTerraformBlock(block *TerraformBlock)
- func (s *Stack) SetVariables(variables []*Variable)
- func (s *Stack) Write(w io.Writer) error
- type Stacks
- type TerraformBlock
- type TerraformConfig
- type Variable
- type Variables
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MarshalJSON ¶
MarshalJSON encodes v to indented JSON with HTML escaping disabled.
func OutputFile ¶
OutputFile creates the parent directories and file at the given path.
Types ¶
type Backend ¶
Backend represents the backend configuration in the terraform block, which includes the type of backend and its configuration.
type Config ¶
Config is a free-form set of Terraform configuration attributes, used for the body of resources, data sources, modules, providers, and backends. The keys and values map directly onto Terraform's JSON syntax.
Its underlying type is map[string]any, so a plain map literal works anywhere a Config is expected, and vice versa.
type Data ¶
type Data struct {
Type string // data source type, e.g. "aws_ami"
Name string // local name, unique per type within the stack
Config Config // the data source's arguments
}
Data represents a data source block in a Terraform configuration.
type Generator ¶
type Generator interface {
// Validate checks that the generator's configuration is valid. This should
// be called before GenerateStacks to catch config errors early.
Validate() error
// GenerateStacks generates one or more Terraform stacks based on the
// generator's configuration. The generated stacks can then be written to
// files or applied using a Terraform-compatible CLI.
GenerateStacks() (Stacks, error)
}
Generator produces one or more Terraform stacks from some configuration. Implement it to organise larger configuration-generation logic behind a single, testable entry point.
type Module ¶
type Module struct {
Name string // local name of the module instance
Source string // module source address
Version string // optional version constraint (registry modules only)
Config Config // input variables passed to the module
}
Module represents a module block in a Terraform configuration.
type ModuleSource ¶
type ModuleSource struct {
Name string // module name, e.g. "vpc", "eks-cluster"
Provider string // provider namespace, e.g. "aws", "google"
SubDir string // optional subdirectory within {provider}/
}
ModuleSource derives a module's Source from a consistent naming convention, whether the module lives in a registry or on the local filesystem. It follows Terraform's terraform-<PROVIDER>-<NAME> convention:
- Registry: {registryPrefix}/{name}/{provider}
- Local: {modulesDir}/{provider}/terraform-{provider}-{name}
SubDir inserts an additional directory between the provider and the module directory when computing the local path:
- Local with SubDir: {modulesDir}/{provider}/{subDir}/terraform-{provider}-{name}
Using ModuleSource is optional; you can always set Module.Source directly.
func (ModuleSource) LocalSource ¶
func (ms ModuleSource) LocalSource(modulesDir string) string
LocalSource returns the local module path rooted at modulesDir.
func (ModuleSource) RegistrySource ¶
func (ms ModuleSource) RegistrySource(registryPrefix string) string
RegistrySource returns the registry source path for the given registry prefix. The prefix is the leading portion of a registry module address, such as the host and namespace (e.g. "app.terraform.io/example-org").
type Output ¶
type Output struct {
Name string // output name
Value any // exported value, often a Ref to another block
Description string // optional human-readable description
}
Output represents an output block in a Terraform configuration.
type Provider ¶
type Provider struct {
Name string // provider name, e.g. "aws"
Config Config // provider settings; include "alias" for additional configurations
}
Provider represents a provider block in a Terraform configuration.
type ProviderRequirement ¶
type ProviderRequirement struct {
Source string // provider source address, e.g. "hashicorp/aws"
Version string // version constraint, e.g. "~> 5.0"
}
ProviderRequirement represents the required provider configuration in the terraform block, which includes the source and version of the provider.
type RequiredProviders ¶
type RequiredProviders map[string]ProviderRequirement
RequiredProviders maps a provider's local name to its source and version requirement.
type Resource ¶
type Resource struct {
Type string // resource type, e.g. "aws_s3_bucket"
Name string // local name, unique per type within the stack
Config Config // the resource's arguments
}
Resource represents a resource block in a Terraform configuration.
type Stack ¶
type Stack struct {
// Name is the name of the stack
Name string
// contains filtered or unexported fields
}
Stack represents a Terraform stack which can eventually be written to be applied by a Terraform-compatible CLI, such as Terraform or Tofu.
func NewStack ¶
NewStack creates a new Stack with the given name and an empty Terraform configuration.
func (*Stack) AddProvider ¶
AddProvider appends a provider to the stack.
func (*Stack) AddResource ¶
AddResource appends a resource to the stack.
func (*Stack) AddVariable ¶
AddVariable appends a variable to the stack.
func (*Stack) JSON ¶
JSON returns the JSON representation of the stack's Terraform configuration. This correctly marshals the stack elements into the correct Terraform specification.
func (*Stack) SetModules ¶
SetModules replaces the stack's modules.
func (*Stack) SetOutputs ¶
SetOutputs replaces the stack's outputs.
func (*Stack) SetProviders ¶
SetProviders replaces the stack's providers.
func (*Stack) SetResources ¶
SetResources replaces the stack's resources.
func (*Stack) SetTerraformBlock ¶
func (s *Stack) SetTerraformBlock(block *TerraformBlock)
SetTerraformBlock sets the stack's terraform block.
func (*Stack) SetVariables ¶
SetVariables replaces the stack's variables.
type TerraformBlock ¶
type TerraformBlock struct {
RequiredVersion string // Terraform version constraint, e.g. ">= 1.9"; omitted when empty
RequiredProviders RequiredProviders // provider source and version requirements
Backend *Backend // optional state backend configuration
}
TerraformBlock represents the terraform block in a Terraform configuration, which includes required_version, required_providers, and backend configuration.
func (*TerraformBlock) AddRequiredProvider ¶
func (block *TerraformBlock) AddRequiredProvider(name string, req ProviderRequirement)
AddRequiredProvider records a provider requirement under the given local name, allocating the map if necessary.
type TerraformConfig ¶
type TerraformConfig struct {
Data DataSources // data source blocks
Modules Modules // module blocks
Outputs Outputs // output blocks
Providers Providers // provider blocks
Resources Resources // resource blocks
TerraformBlock *TerraformBlock // the terraform block, if any
Variables Variables // variable blocks
}
TerraformConfig holds the building blocks of a single Terraform configuration: the terraform block, providers, resources, data sources, modules, variables, and outputs.
type Variable ¶
type Variable struct {
Name string // variable name
Type string // Terraform type constraint, e.g. "string", "bool", "map(string)"
Description string // optional human-readable description
Default any // default value; nil marks the variable as required (no default emitted)
}
Variable represents a variable block in a Terraform configuration.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
generate
command
Command generate shows how to drive tfgen from `go generate`.
|
Command generate shows how to drive tfgen from `go generate`. |
|
providers
|
|
|
ably
Package ably provides convenience constructors for the Terraform Ably provider (https://github.com/ably/terraform-provider-ably).
|
Package ably provides convenience constructors for the Terraform Ably provider (https://github.com/ably/terraform-provider-ably). |
|
aws
Package aws provides convenience constructors for the Terraform AWS provider.
|
Package aws provides convenience constructors for the Terraform AWS provider. |
|
cloudflare
Package cloudflare provides convenience constructors for the Terraform Cloudflare provider.
|
Package cloudflare provides convenience constructors for the Terraform Cloudflare provider. |