terraform-provider-hyperv

command module
v0.0.0-...-ab035be Latest Latest
Warning

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

Go to latest
Published: Apr 28, 2026 License: MPL-2.0 Imports: 5 Imported by: 0

README

Terraform Provider for Hyper-V

Manage the lifecycle of Microsoft Hyper-V virtual machines, switches, disks, and images from Terraform — with a provider binary that runs on Linux, macOS, or Windows and talks to Hyper-V hosts over local PowerShell, SSH, or WinRM.

CI Go Report Card Latest Release

[!IMPORTANT] This provider is pre-1.0. Schema, attribute names, and behavior may change between minor versions until v1.0.0 ships. Pin to an exact version in production.

Highlights

  • Pluggable execution backends. local (provider already on the host), ssh (key- or password-auth into the host's OpenSSH), or winrm (HTTP/HTTPS, NTLM/Basic/Kerberos). The provider binary itself runs on Linux, macOS, or Windows.
  • Built on terraform-plugin-framework. Strict typed schemas, plan modifiers, validators, custom semantic-equality types, and Terraform protocol v6.
  • Embedded PowerShell with a JSON contract. Each operation ships an embedded .ps1 through the chosen transport and round-trips JSON via stdin/stdout. Scripts are independently testable with Pester.

Supported resources and data sources

Resource Subcategory Notes
hyperv_virtual_switch Networking External / Internal / Private switches; NIC team binding; management OS share toggle.
hyperv_vm_network_adapter Networking Per-VM NICs with VLAN, MAC, and bandwidth limits.
hyperv_image_file Storage Place a VHDX or ISO on the host. Modes: url, host_path, local_path, content, cloud_init (NoCloud seed-ISO synthesis), unattend (Windows answer-file ISO synthesis).
hyperv_vhd Storage Fixed / dynamic / differencing VHD or VHDX. Resizable for dynamic.
hyperv_vm_hard_disk_drive Storage Attaches an existing hyperv_vhd to a VM at a controller location.
hyperv_vm_dvd_drive Storage ISO attachment with eject-on-destroy semantics for appliance-OS workflows.
hyperv_vm Compute Generation 1/2, CPU, memory (static or dynamic), Secure Boot, integration services, boot order, automatic start/stop.
hyperv_vm_state Compute Operational state (running/off/saved/paused); optionally waits for an IP and exposes ip_addresses.
hyperv_vm_checkpoint Compute Production or standard checkpoints.
Data source Subcategory
hyperv_host Host
hyperv_vm Compute
hyperv_virtual_switch Networking

Out of scope for v1: replication, live migration, SR-IOV, GPU partitioning, shielded VMs, image creation (build golden images with Packer or DISM and reference them via hyperv_image_file).

Requirements

Runtime
  • Terraform >= 1.5
  • A Hyper-V host running Windows Server 2019+ or Windows 10/11 Pro/Enterprise with the Hyper-V role enabled.
  • Windows PowerShell 5.1 on the host (ships with Windows). PowerShell 7.4+ is supported and tested but not required.
  • One reachable transport to the host: a local PowerShell installation, OpenSSH, or WinRM (HTTPS recommended).
Development
  • Go matching the toolchain in go.mod (currently 1.25+).
  • Task for the build, lint, test, and docs targets.
  • aqua to provision pinned versions of terraform, goreleaser, gosec, etc. (see aqua.yaml).
  • PowerShell 7+ to run the Pester script-level tests.
  • A reachable Hyper-V host for acceptance tests (task test:acc); unit tests run anywhere.

Quickstart

terraform {
  required_providers {
    hyperv = {
      source  = "windsorcli/hyperv"
      version = "~> 0.1"
    }
  }
}

# Configuration is environment-driven by default; see "Configuration" below.
provider "hyperv" {}

resource "hyperv_virtual_switch" "lab" {
  name        = "lab-internal"
  switch_type = "Internal"
}

resource "hyperv_image_file" "ubuntu" {
  destination_path = "C:\\hyperv\\images\\ubuntu-22.04.vhdx"
  url = {
    url      = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.vhdx"
    checksum = "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
  }
}

resource "hyperv_vhd" "vm01_root" {
  path        = "C:\\hyperv\\vhds\\vm01-root.vhdx"
  vhd_type    = "differencing"
  parent_path = hyperv_image_file.ubuntu.destination_path
}

A complete end-to-end example (URL fetch → differencing VHD → cloud-init seed ISO → VM → power on → wait for IP) lives under examples/ and on the Terraform Registry.

Configuration

Every provider attribute has a corresponding HYPERV_* environment variable. Precedence: provider attribute > env var > zero/error. Omitting the provider block entirely makes env vars the sole source — useful for shared modules where each user supplies their own host.

Local backend (provider runs on the Hyper-V host)
provider "hyperv" {
  backend = "local"
}
SSH backend
provider "hyperv" {
  backend  = "ssh"
  host     = "hv01.lab"
  username = "Administrator"
  ssh = {
    private_key_path = "~/.ssh/id_ed25519"
  }
}

The host needs OpenSSH Server enabled with PowerShell as the default shell. See docs/guides/host-setup.md.

WinRM backend
provider "hyperv" {
  backend  = "winrm"
  host     = "hv01.lab"
  username = "Administrator"
  password = var.hv_password
  winrm = {
    use_https = true
    auth      = "ntlm"
  }
}

WinRM HTTPS with NTLM is the recommended configuration for workgroup hosts; Kerberos is supported in domain environments. See docs/guides/host-setup.md for the host-side WSMan configuration.

Environment variables
Variable Attribute Notes
HYPERV_BACKEND backend local | ssh | winrm
HYPERV_HOST host Required for ssh / winrm
HYPERV_PORT port Defaults: 22 (ssh), 5986 (winrm)
HYPERV_USERNAME username Required for ssh / winrm
HYPERV_PASSWORD password Sensitive
HYPERV_TIMEOUT timeout Per-call PS execution timeout (Go duration)
HYPERV_SSH_PRIVATE_KEY ssh.private_key Sensitive; key contents
HYPERV_SSH_PRIVATE_KEY_PATH ssh.private_key_path Path alternative
HYPERV_SSH_PASSPHRASE ssh.passphrase Sensitive
HYPERV_SSH_KNOWN_HOSTS_PATH ssh.known_hosts_path Defaults to ~/.ssh/known_hosts
HYPERV_WINRM_USE_HTTPS winrm.use_https Defaults to true
HYPERV_WINRM_INSECURE winrm.insecure Skip TLS verify
HYPERV_WINRM_AUTH winrm.auth basic | ntlm | kerberos
HYPERV_WINRM_CACERT winrm.cacert Path to a CA bundle
HYPERV_PWSH_PATH local.pwsh_path Override PowerShell binary discovery

A complete .env.example is committed at the repository root.

Documentation

Building from source

git clone https://github.com/windsorcli/terraform-provider-hyperv.git
cd terraform-provider-hyperv
task tools          # install pinned dev tools
task                # default: lint + unit tests
task build          # build the provider binary for the current platform
task install        # install to ~/.terraform.d/plugins/ for local Terraform use

To use a locally built provider in a Terraform configuration without publishing, add a dev_overrides block to ~/.terraformrc:

provider_installation {
  dev_overrides {
    "windsorcli/hyperv" = "/Users/<you>/go/bin"
  }
  direct {}
}

task install writes the binary to ~/.terraform.d/plugins/registry.terraform.io/windsorcli/hyperv/0.0.0-dev/<os>_<arch>/; with the override above pointing at $GOPATH/bin, run go install to drop the binary there directly.

Testing

The provider is exercised in three tiers, each runnable independently:

task test:unit      # Go unit tests, no Hyper-V required (fakes the PS runner)
task test:pester    # Pester tests for the embedded .ps1 scripts (PowerShell 7+)
task test:acc       # acceptance tests against a real Hyper-V host

[!CAUTION] task test:acc creates real Hyper-V resources — virtual switches, VMs, disks. Run only against a host you own. Sweepers (task sweep) clean up orphaned resources prefixed with the test name. Tests are gated on TF_ACC=1.

Acceptance test configuration lives in .env.local (gitignored); copy .env.example and fill in HYPERV_* values for the backend you want to exercise. The CI matrix runs acceptance against Server 2019 (PS 5.1 only) and Server 2022 (PS 7.4 alongside 5.1) on each of the three backends.

Debugging

  • TF_LOG=DEBUG — standard Terraform log level; surfaces provider-level messages.
  • TF_LOG_PROVIDER=DEBUG — provider-only logs; quieter than TF_LOG.
  • TF_LOG_PROVIDER_HYPERV_CONNECTION=DEBUG — connection-subsystem logs (transport, auth, pooling) without the resource-CRUD chatter.
  • TF_LOG_PROVIDER=TRACE — full PS stdin/stdout/stderr per call. Sensitive values are masked, but enable only when debugging.

To attach a debugger, build with task build and run the provider with -debug; Terraform will print a TF_REATTACH_PROVIDERS env var to set in the shell that runs terraform plan or terraform apply.

Known limitations

  • No image creation. Use Packer or DISM to build golden images and reference them via hyperv_image_file.
  • PowerShell startup latency. Each operation pays the cost of a pwsh/powershell.exe invocation: ~1.4s per call over SSH, ~2.0s over WinRM, ~0.5–0.8s locally. Terraform's default 10-way parallelism absorbs this for typical fleets; persistent-runspace mode is on the v1 stretch-goal list for >100-resource deployments.
  • WinRM local_path transfers cap at 100 MB. Use url (host-side BITS fetch) or host_path for larger files.
  • Cancel-mid-cmdlet may leave partial state. A New-VM interrupted after disk creation but before VM registration will require either a re-apply or a manual cleanup.
  • Differencing parent paths surface errors at apply time, not plan time. New-VHD validates the parent path in ~400ms; the provider maps the cmdlet error to an attribute-level diagnostic.

See docs/PLAN.md §11.5 for the full list and rationale.

Contributing

Contributions are welcome. For non-trivial changes — new resources, schema changes, new backends — please open an issue first to align on shape before writing code. Bug fixes and documentation improvements can go straight to a PR.

The repository follows strict TDD: PowerShell scripts get Pester tests first to lock the JSON contract, then Go unit tests with a fake runner, then resource schema tests, then acceptance tests, then implementation. See docs/PLAN.md §9 for the full strategy.

PRs require:

  • A release-drafter label (feature, fix, chore, documentation, dependencies, breaking, etc.) — enforced in CI.
  • All task lint, task test:unit, task validate:examples, task docs:check, and task docs:validate jobs green.
  • Acceptance tests passing on at least one backend (the acc-test label gates the self-hosted runner pool).

License

This provider is distributed under the Mozilla Public License 2.0.

Documentation

Overview

Terraform provider for Hyper-V. Entry point.

Real provider behavior lives under internal/provider. This file does only the minimum needed for `terraform init` to discover us: parse a -debug flag, then hand off to providerserver.Serve.

Directories

Path Synopsis
internal
acctest
Package acctest provides acceptance-test scaffolding shared across resource packages.
Package acctest provides acceptance-test scaffolding shared across resource packages.
connection
Package connection defines the transport abstraction the typed Hyper-V client (internal/hyperv) uses to ship PowerShell scripts to a Windows host and read their results back.
Package connection defines the transport abstraction the typed Hyper-V client (internal/hyperv) uses to ship PowerShell scripts to a Windows host and read their results back.
datasources/host
Package host implements the hyperv_host data source — read-only information about the Hyper-V host.
Package host implements the hyperv_host data source — read-only information about the Hyper-V host.
datasources/vswitch
Package vswitch implements the hyperv_virtual_switch data source -- read-only access to an existing switch by name.
Package vswitch implements the hyperv_virtual_switch data source -- read-only access to an existing switch by name.
hyperv
Package hyperv is the typed Go wrapper over the connection layer.
Package hyperv is the typed Go wrapper over the connection layer.
provider
Package provider implements the Hyper-V Terraform provider.
Package provider implements the Hyper-V Terraform provider.
resources/image_file
Package image_file implements the hyperv_image_file resource.
Package image_file implements the hyperv_image_file resource.
resources/vhd
Package vhd implements the hyperv_vhd resource.
Package vhd implements the hyperv_vhd resource.
resources/vm
Package vm implements the hyperv_vm resource (M4 minimal first slice).
Package vm implements the hyperv_vm resource (M4 minimal first slice).
resources/vswitch
Package vswitch implements the hyperv_virtual_switch resource.
Package vswitch implements the hyperv_virtual_switch resource.
scripts
Package scripts embeds the PowerShell scripts the provider runs against the host.
Package scripts embeds the PowerShell scripts the provider runs against the host.
testutil
Package testutil provides shared test helpers — primarily a deterministic fake of connection.Runner that lets typed-client tests exercise the JSON contract without needing a real Hyper-V host or even a real pwsh binary.
Package testutil provides shared test helpers — primarily a deterministic fake of connection.Runner that lets typed-client tests exercise the JSON contract without needing a real Hyper-V host or even a real pwsh binary.
types/path
Package path provides a custom Terraform attribute type for Windows file paths used by the Hyper-V provider.
Package path provides a custom Terraform attribute type for Windows file paths used by the Hyper-V provider.

Jump to

Keyboard shortcuts

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