iac

package
v0.0.0-...-1b78e83 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 17, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

README

iac

Infrastructure-as-Code plugin framework for cldctl. Provides a unified interface for different IaC tools including native Docker execution, OpenTofu/Terraform, and Pulumi.

Overview

The iac package provides:

  • A common Plugin interface for IaC frameworks
  • A registry system for managing plugin factories
  • Built-in plugins for native execution, OpenTofu/Terraform, and Pulumi

Package Structure

iac/
├── plugin.go       # Plugin interface and types
├── registry.go     # Plugin registry
├── native/         # Native Docker/exec plugin
├── opentofu/       # OpenTofu/Terraform plugin
└── pulumi/         # Pulumi plugin

Plugin Interface

All IaC plugins implement a common interface:

type Plugin interface {
    Name() string
    Preview(ctx context.Context, opts RunOptions) (*PreviewResult, error)
    Apply(ctx context.Context, opts RunOptions) (*ApplyResult, error)
    Destroy(ctx context.Context, opts RunOptions) (*ApplyResult, error)
    Refresh(ctx context.Context, opts RunOptions) (*RefreshResult, error)
}

Types

RunOptions

Configuration for plugin execution.

type RunOptions struct {
    WorkDir       string
    Inputs        map[string]interface{}
    State         []byte
    Volumes       []VolumeMount
    Output        *output.Stream
    AutoApprove   bool
}
Result Types
type PreviewResult struct {
    Changes []ResourceChange
    Summary ChangeSummary
}

type ApplyResult struct {
    Success bool
    Outputs map[string]OutputValue
    State   []byte
}

type RefreshResult struct {
    Drift []ResourceDrift
    State []byte
}
Change Actions
const (
    ActionCreate  ChangeAction = "create"
    ActionUpdate  ChangeAction = "update"
    ActionDelete  ChangeAction = "delete"
    ActionReplace ChangeAction = "replace"
    ActionNoop    ChangeAction = "noop"
)

Registry

The registry manages plugin factories and provides plugin instances.

// Register a plugin factory
iac.Register("myplugin", func() (iac.Plugin, error) {
    return NewMyPlugin()
})

// Get a plugin instance
plugin, err := iac.Get("opentofu")

// List available plugins
plugins := iac.DefaultRegistry.List()

Subpackages

native

Native IaC plugin for Docker and process execution. Executes Docker containers, networks, volumes, and host commands directly without external IaC tools.

import "github.com/davidthor/cldctl/pkg/iac/native"

// Create a native plugin
plugin, err := native.NewPlugin()

// Load a native module definition
module, err := native.LoadModule("./module.yml")

// Direct Docker client usage
docker, err := native.NewDockerClient()
err = docker.RunContainer(ctx, native.ContainerOptions{
    Name:  "my-container",
    Image: "nginx:latest",
    Ports: []native.PortMapping{{Host: 8080, Container: 80}},
})

Supported Resource Types:

  • docker:container - Docker containers
  • docker:network - Docker networks
  • docker:volume - Docker volumes
  • exec - One-time command execution

Docker Client Methods:

  • RunContainer(), InspectContainer(), IsContainerRunning(), RemoveContainer()
  • CreateNetwork(), NetworkExists(), RemoveNetwork()
  • CreateVolume(), VolumeExists(), RemoveVolume()
  • Exec() - Execute a command on the host
  • BuildImage(), PushImage(), TagImage(), RemoveImage()

Expression Support:

resources:
  - name: api
    type: docker:container
    properties:
      image: ${inputs.image}
      env:
        DATABASE_URL: ${resources.db.outputs.url}
opentofu

IaC plugin for OpenTofu/Terraform. Wraps the tofu or terraform binary.

import "github.com/davidthor/cldctl/pkg/iac/opentofu"

// Create a plugin (auto-detects tofu or terraform binary)
plugin, err := opentofu.NewPlugin("tofu")  // or "terraform"

Features:

  • Auto-detects tofu or terraform binary
  • Registers as both "opentofu" and "terraform" plugins
  • Writes terraform.tfvars.json from inputs
  • Handles initialization automatically
  • Parses JSON plan output for preview
  • Reads state from terraform.tfstate
pulumi

IaC plugin for Pulumi. Wraps the pulumi binary.

import "github.com/davidthor/cldctl/pkg/iac/pulumi"

// Create a Pulumi plugin
plugin, err := pulumi.NewPlugin()

Features:

  • Stack management (auto-creates/selects stacks)
  • Writes Pulumi.<stack>.yaml config files from inputs
  • Stack name resolution from environment variables
  • Parses JSON preview output
  • Exports state via pulumi stack export
  • Uses local backend by default

Usage Example

import (
    "github.com/davidthor/cldctl/pkg/iac"
    "github.com/davidthor/cldctl/pkg/output"
)

// Get a plugin
plugin, err := iac.Get("opentofu")
if err != nil {
    log.Fatal(err)
}

// Create output stream
stream := output.NewStream()
stream.AddHandler(output.NewConsoleHandler(output.ConsoleOptions{
    UseColors: true,
}))

// Preview changes
preview, err := plugin.Preview(ctx, iac.RunOptions{
    WorkDir: "./infrastructure",
    Inputs: map[string]interface{}{
        "region":   "us-west-2",
        "replicas": 3,
    },
    Output: stream,
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Changes: +%d ~%d -%d\n",
    preview.Summary.ToCreate,
    preview.Summary.ToUpdate,
    preview.Summary.ToDelete)

// Apply changes
result, err := plugin.Apply(ctx, iac.RunOptions{
    WorkDir:     "./infrastructure",
    Inputs:      inputs,
    Output:      stream,
    AutoApprove: true,
})
if err != nil {
    log.Fatal(err)
}

// Access outputs
for name, output := range result.Outputs {
    fmt.Printf("%s = %v\n", name, output.Value)
}

Plugin Registration

All built-in plugins register themselves via init() functions:

func init() {
    iac.Register("native", func() (iac.Plugin, error) {
        return native.NewPlugin()
    })
    iac.Register("opentofu", func() (iac.Plugin, error) {
        return opentofu.NewPlugin("tofu")
    })
    iac.Register("terraform", func() (iac.Plugin, error) {
        return opentofu.NewPlugin("terraform")
    })
    iac.Register("pulumi", func() (iac.Plugin, error) {
        return pulumi.NewPlugin()
    })
}

Creating Custom Plugins

Implement the Plugin interface:

type MyPlugin struct{}

func (p *MyPlugin) Name() string {
    return "myplugin"
}

func (p *MyPlugin) Preview(ctx context.Context, opts iac.RunOptions) (*iac.PreviewResult, error) {
    // Implement preview logic
}

func (p *MyPlugin) Apply(ctx context.Context, opts iac.RunOptions) (*iac.ApplyResult, error) {
    // Implement apply logic
}

func (p *MyPlugin) Destroy(ctx context.Context, opts iac.RunOptions) (*iac.ApplyResult, error) {
    // Implement destroy logic
}

func (p *MyPlugin) Refresh(ctx context.Context, opts iac.RunOptions) (*iac.RefreshResult, error) {
    // Implement refresh logic
}

// Register the plugin
func init() {
    iac.Register("myplugin", func() (iac.Plugin, error) {
        return &MyPlugin{}, nil
    })
}

Documentation

Overview

Package iac provides the Infrastructure-as-Code plugin framework.

Index

Constants

This section is empty.

Variables

View Source
var DefaultRegistry = &Registry{
	factories: make(map[string]Factory),
}

DefaultRegistry is the global plugin registry.

Functions

func Register

func Register(name string, factory Factory)

Register registers a plugin factory with the default registry.

Types

type ApplyResult

type ApplyResult struct {
	Outputs map[string]OutputValue
	State   []byte // Serialized state for persistence

	// PartialError is set if apply partially succeeded
	PartialError error
}

ApplyResult contains the result of an apply operation.

type ChangeAction

type ChangeAction string

ChangeAction indicates the type of change.

const (
	ActionCreate  ChangeAction = "create"
	ActionUpdate  ChangeAction = "update"
	ActionDelete  ChangeAction = "delete"
	ActionReplace ChangeAction = "replace"
	ActionNoop    ChangeAction = "noop"
)

type ChangeSummary

type ChangeSummary struct {
	Create  int
	Update  int
	Delete  int
	Replace int
}

ChangeSummary summarizes planned changes.

type Factory

type Factory func() (Plugin, error)

Factory creates a plugin instance.

type ImportMapping

type ImportMapping struct {
	// Address is the IaC-module-internal resource address (e.g., "aws_db_instance.main")
	Address string

	// ID is the real cloud resource ID (e.g., "mydb-instance-123")
	ID string
}

ImportMapping maps an IaC resource address to a cloud resource ID.

type ImportOptions

type ImportOptions struct {
	// ModuleSource is the OCI image reference or local path to the module
	ModuleSource string

	// ModulePath is the path within the module (for local modules)
	ModulePath string

	// Inputs are the values passed to the module
	Inputs map[string]interface{}

	// Mappings are the resource address to cloud ID mappings
	Mappings []ImportMapping

	// WorkDir is the working directory for execution
	WorkDir string

	// Environment contains environment variables for the execution
	Environment map[string]string

	// Stdout/Stderr for command output
	Stdout io.Writer
	Stderr io.Writer
}

ImportOptions configures an import operation.

type ImportResult

type ImportResult struct {
	// Outputs extracted from the imported state
	Outputs map[string]OutputValue

	// State is the serialized IaC state after import
	State []byte

	// ImportedResources lists the addresses that were successfully imported
	ImportedResources []string
}

ImportResult contains the result of an import operation.

type OutputValue

type OutputValue struct {
	Value     interface{}
	Sensitive bool
}

OutputValue represents a module output.

type Plugin

type Plugin interface {
	// Name returns the plugin identifier (e.g., "pulumi", "opentofu", "native")
	Name() string

	// Preview generates a preview of changes without applying
	Preview(ctx context.Context, opts RunOptions) (*PreviewResult, error)

	// Apply applies the module and returns outputs
	Apply(ctx context.Context, opts RunOptions) (*ApplyResult, error)

	// Destroy destroys resources created by the module
	Destroy(ctx context.Context, opts RunOptions) error

	// Refresh refreshes state without applying changes
	Refresh(ctx context.Context, opts RunOptions) (*RefreshResult, error)

	// Import adopts existing cloud resources into the module's state.
	// Each ImportMapping maps an IaC-internal resource address to a real cloud
	// resource ID. After importing, the plugin extracts outputs from the
	// resulting state so cldctl can record them.
	Import(ctx context.Context, opts ImportOptions) (*ImportResult, error)
}

Plugin defines the interface for IaC framework plugins.

func Get

func Get(name string) (Plugin, error)

Get retrieves a plugin from the default registry.

type PreviewResult

type PreviewResult struct {
	Changes []ResourceChange
	Summary ChangeSummary
}

PreviewResult contains the result of a preview operation.

type PropertyDiff

type PropertyDiff struct {
	Path      string
	OldValue  interface{}
	NewValue  interface{}
	Sensitive bool
}

PropertyDiff describes a change to a property.

type RefreshResult

type RefreshResult struct {
	State  []byte
	Drifts []ResourceDrift
}

RefreshResult contains the result of a refresh operation.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry manages plugin factories.

func (*Registry) Get

func (r *Registry) Get(name string) (Plugin, error)

Get retrieves a plugin by name.

func (*Registry) List

func (r *Registry) List() []string

List returns all registered plugin names.

func (*Registry) Register

func (r *Registry) Register(name string, factory Factory)

Register adds a plugin factory to the registry.

type ResourceChange

type ResourceChange struct {
	ResourceID   string
	ResourceType string
	Action       ChangeAction // Create, Update, Delete, Replace
	Before       interface{}  // Current state (nil for create)
	After        interface{}  // Planned state (nil for delete)
	Diff         []PropertyDiff
}

ResourceChange describes a planned change to a resource.

type ResourceDrift

type ResourceDrift struct {
	ResourceID   string
	ResourceType string
	Diffs        []PropertyDiff
}

ResourceDrift describes drift between state and actual infrastructure.

type RunOptions

type RunOptions struct {
	// ModuleSource is the OCI image reference or local path to the module
	ModuleSource string

	// ModulePath is the path within the module (for local modules)
	ModulePath string

	// Inputs are the values passed to the module
	Inputs map[string]interface{}

	// StateReader provides existing state (nil for new deployments)
	StateReader io.Reader

	// StateWriter receives the updated state after apply
	StateWriter io.Writer

	// WorkDir is the working directory for execution
	WorkDir string

	// Environment contains environment variables for the execution
	Environment map[string]string

	// Volumes are volume mounts needed by the module (e.g., Docker socket)
	Volumes []VolumeMount

	// Stdout/Stderr for command output
	Stdout io.Writer
	Stderr io.Writer

	// OnProgress reports sub-status updates during long-running operations
	// (e.g., "pulling image...", "health check 5/30"). May be nil.
	OnProgress func(message string)
}

RunOptions configures a plugin execution.

type VolumeMount

type VolumeMount struct {
	HostPath  string
	MountPath string
	ReadOnly  bool
}

VolumeMount defines a volume mount for module execution.

Directories

Path Synopsis
Package container implements container-based IaC module execution.
Package container implements container-based IaC module execution.
entrypoint command
Package main implements the cldctl module entrypoint.
Package main implements the cldctl module entrypoint.
Package native implements a native IaC plugin for Docker and process execution.
Package native implements a native IaC plugin for Docker and process execution.
Package opentofu implements an IaC plugin for OpenTofu/Terraform.
Package opentofu implements an IaC plugin for OpenTofu/Terraform.
Package pulumi implements an IaC plugin for Pulumi.
Package pulumi implements an IaC plugin for Pulumi.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL