obm/internal/terraform/terraform.go
MermaidMan ab1de96168 migrate to OpenTofu with Terraform fallback
Add binary lookup in both terraform.go and destroy.go:
tofu preferred, terraform fallback. Update all docs to
reflect the OpenTofu-first approach.
2026-06-04 17:46:40 +00:00

63 lines
1.4 KiB
Go

// Package terraform wraps IaC operations (init, plan, apply, destroy).
// Supports OpenTofu (preferred) and Terraform (fallback).
package terraform
import (
"fmt"
"os/exec"
)
// binary returns the path to the IaC binary: tofu preferred, terraform fallback.
func binary() string {
for _, name := range []string{"tofu", "terraform"} {
if path, err := exec.LookPath(name); err == nil {
return path
}
}
return "tofu" // fallback — will produce a useful error at runtime
}
// Runner executes infrastructure-as-code commands.
type Runner struct {
WorkDir string
}
// NewRunner creates a runner for the given working directory.
func NewRunner(workDir string) *Runner {
return &Runner{WorkDir: workDir}
}
// Init runs init.
func (r *Runner) Init() error {
return r.run("init", "-input=false")
}
// Plan runs plan.
func (r *Runner) Plan(destroy bool) error {
args := []string{"plan"}
if destroy {
args = append(args, "-destroy")
}
return r.run(args...)
}
// Apply runs apply.
func (r *Runner) Apply() error {
return r.run("apply", "-auto-approve")
}
// Destroy runs destroy.
func (r *Runner) Destroy() error {
return r.run("destroy", "-auto-approve")
}
func (r *Runner) run(args ...string) error {
bin := binary()
cmd := exec.Command(bin, args...)
cmd.Dir = r.WorkDir
output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("%s %v: %w\n%s", bin, args, err, output)
}
return nil
}