This is a HashiCorp Packer plugin for creating Linode images. It provides:
- Builder (
builder/linode/): Creates Linode instances, provisions them, then snapshots to reusable images - Datasource (
datasource/image/): Queries existing Linode images for use in Packer templates
The plugin uses the Packer Plugin SDK and linodego client library.
main.goregisters the builder and datasource with the Packer plugin system- Builder executes as a series of steps (
step_*.go) viamultistep.Runner:StepCreateSSHKey→stepCreateLinode→stepCreateDiskConfig→StepConnect→StepProvision→stepShutdownLinode→stepCreateImage
- Configuration is defined in
config.gowith HCL2 specs auto-generated via//go:generate packer-sdc
The builder supports two modes:
Standard Mode (with image specified):
- Linode API automatically creates disk and config from the image
- Instance starts booted and ready for SSH connection
- Used in most scenarios
Custom Mode (with disk and config blocks):
stepCreateLinodecreates unbooted instance without imagestepCreateDiskConfigcreates custom disks and configuration profiles- Disk label → ID resolution: configs reference disks by label, which are resolved after disk creation
- At most one config may have
booted = true; if none do, the first config is used as the boot configuration - Instance is manually booted after configuration
- Enables fine-grained control over disk layout, kernel, helpers, and interfaces
- Configuration structs use
mapstructuretags for HCL parsing and embedhelper.LinodeCommonfor shared auth config - Step pattern: Each step implements
multistep.Stepinterface withRun()andCleanup()methods, storing state inmultistep.StateBag - Flatten functions in
step_create_linode.goandstep_create_disk_config.goconvert config structs to linodego API types - Disk label resolution:
resolveDiskLabel()instep_create_disk_config.gomaps user-provided disk labels in configs to actual disk IDs after creation - Two interface systems: Legacy
interfaceblocks and newerlinode_interfaceblocks (seelinode_interfaces.go)
- Create
step_<name>.goimplementingmultistep.StepwithRun(ctx, state)andCleanup(state)methods - Retrieve config/ui from state:
c := state.Get("config").(*Config),ui := state.Get("ui").(packersdk.Ui) - Use
helper.ErrorHelper(state, ui, "prefix", err)for error handling (returnsmultistep.ActionHalt) - Store results in state for subsequent steps:
state.Put("key", value) - Add step to the
stepsslice inbuilder.goRun()method in correct order - Implement
Cleanup()for resource teardown on failure (e.g., delete created resources)
make dev # Build plugin and install to Packer plugins dir
make unit-test # Run unit tests with race detection
make acctest # Run acceptance tests (requires PACKER_ACC=1, LINODE_TOKEN)
make generate # Regenerate HCL2 specs and documentation
make lint # Run golangci-lint (install via `make deps`)
make format # Format code with gofumpt- Unit tests: No external dependencies, run with
make unit-test - Acceptance tests: Require
LINODE_TOKENenv var andPACKER_ACC=1, create real Linode resources - Test files follow
*_test.gonaming; acceptance tests use*_acc_test.gosuffix - Debug with
PACKER_LOG=1environment variable to see detailed plugin logs
Files ending in .hcl2spec.go are auto-generated – do not edit manually. When modifying config structs:
- Add/update
//go:generate packer-sdc struct-markdownand//go:generate packer-sdc mapstructure-to-hcl2directives - Run
make generateto regenerate specs and docs - Documentation partials in
docs-partials/are generated from struct field comments
- Add field to struct in
config.goorlinode_interfaces.gowithmapstructuretag - Add doc comment above field (becomes auto-generated documentation)
- Mark required fields with
required:"true"tag - Add validation in
Config.Prepare()method if needed - Run
make generateto update.hcl2spec.goand docs
| Path | Purpose |
|---|---|
builder/linode/config.go |
Builder configuration with validation |
builder/linode/step_*.go |
Build step implementations |
builder/linode/step_create_disk_config.go |
Custom disk and config profile creation step |
builder/linode/linode_interfaces.go |
Newer network interface configuration structs |
helper/common.go |
Shared config (LinodeCommon embedded struct) |
helper/client.go |
Linode API client initialization |
helper/error.go |
ErrorHelper for consistent step error handling |
datasource/image/data.go |
Image datasource implementation |
docs/ |
MDX documentation source files |
example/ |
Sample Packer templates (HCL and JSON) |