Documentation
¶
Overview ¶
Package vm implements the hyperv_vm resource, wrapping the vm/{get,new,set,remove}.ps1 contract via the typed hyperv.Client. CPU and memory live in nested blocks per ADR-0001.
Index ¶
- Variables
- func BootOrderListFromSlice(ctx context.Context, slice []BootOrderEntryModel) (types.List, diag.Diagnostics)
- func DvdDriveListFromSlice(ctx context.Context, slice []DvdDriveModel) (types.List, diag.Diagnostics)
- func HardDiskDriveListFromSlice(ctx context.Context, slice []HardDiskDriveModel) (types.List, diag.Diagnostics)
- func NetworkAdapterListFromSlice(ctx context.Context, slice []NetworkAdapterModel) (types.List, diag.Diagnostics)
- func New() resource.Resource
- type BootOrderEntryModel
- type CPUModel
- type DvdDriveModel
- type HardDiskDriveModel
- type MemoryModel
- type Model
- func (m *Model) BootOrderEntries(ctx context.Context) ([]BootOrderEntryModel, diag.Diagnostics)
- func (m *Model) DvdDriveModels(ctx context.Context) ([]DvdDriveModel, diag.Diagnostics)
- func (m *Model) HardDiskDriveModels(ctx context.Context) ([]HardDiskDriveModel, diag.Diagnostics)
- func (m *Model) NetworkAdapterModels(ctx context.Context) ([]NetworkAdapterModel, diag.Diagnostics)
- type NetworkAdapterModel
- type Resource
- func (r *Resource) ConfigValidators(_ context.Context) []resource.ConfigValidator
- func (r *Resource) Configure(_ context.Context, req resource.ConfigureRequest, ...)
- func (r *Resource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse)
- func (r *Resource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse)
- func (r *Resource) ImportState(ctx context.Context, req resource.ImportStateRequest, ...)
- func (r *Resource) Metadata(_ context.Context, req resource.MetadataRequest, ...)
- func (r *Resource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse)
- func (r *Resource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse)
- func (r *Resource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse)
- func (r *Resource) UpgradeState(_ context.Context) map[int64]resource.StateUpgrader
- type StateModel
Constants ¶
This section is empty.
Variables ¶
var BootOrderEntryAttrTypes = map[string]attr.Type{ "type": types.StringType, "controller_type": types.StringType, "controller_number": types.Int64Type, "controller_location": types.Int64Type, "name": types.StringType, }
BootOrderEntryAttrTypes mirrors BootOrderEntryModel's tfsdk-tagged fields. Same role as DvdDriveAttrTypes for the boot_order list.
var BootOrderEntryListElementType = types.ObjectType{AttrTypes: BootOrderEntryAttrTypes}
BootOrderEntryListElementType is the Object element type the boot_order list holds.
var DvdDriveAttrTypes = map[string]attr.Type{ "iso_path": pathtype.Type, "controller_type": types.StringType, "controller_number": types.Int64Type, "controller_location": types.Int64Type, }
DvdDriveAttrTypes mirrors DvdDriveModel's tfsdk-tagged fields. Used by the Object element type that backs the dvd_drive list, by the helpers below for ListValueFrom / ElementsAs round-trips, and by schema.go's Default empty-list value.
var DvdDriveListElementType = types.ObjectType{AttrTypes: DvdDriveAttrTypes}
DvdDriveListElementType is the Object element type the dvd_drive list holds. Computed once so all helpers share the same instance.
var HardDiskDriveAttrTypes = map[string]attr.Type{ "path": pathtype.Type, "controller_type": types.StringType, "controller_number": types.Int64Type, "controller_location": types.Int64Type, }
HardDiskDriveAttrTypes mirrors HardDiskDriveModel's tfsdk tags.
var HardDiskDriveListElementType = types.ObjectType{AttrTypes: HardDiskDriveAttrTypes}
HardDiskDriveListElementType is the Object type hard_disk_drive elements use.
var NetworkAdapterAttrTypes = map[string]attr.Type{ "name": types.StringType, "switch_name": types.StringType, "ip_addresses": types.ListType{ElemType: types.StringType}, "mac_address": mactype.Type, "vlan_id": types.Int64Type, }
NetworkAdapterAttrTypes mirrors NetworkAdapterModel's tfsdk tags.
var NetworkAdapterListElementType = types.ObjectType{AttrTypes: NetworkAdapterAttrTypes}
NetworkAdapterListElementType is the Object type network_adapter elements use.
Functions ¶
func BootOrderListFromSlice ¶ added in v0.3.0
func BootOrderListFromSlice(ctx context.Context, slice []BootOrderEntryModel) (types.List, diag.Diagnostics)
BootOrderListFromSlice builds a types.List from a typed slice. Nil slice -> null list; empty slice -> empty list. Same rationale as DvdDriveListFromSlice.
func DvdDriveListFromSlice ¶ added in v0.3.0
func DvdDriveListFromSlice(ctx context.Context, slice []DvdDriveModel) (types.List, diag.Diagnostics)
DvdDriveListFromSlice builds a types.List from a typed slice. A nil slice becomes a null list (matching the "DvdDrives not managed" semantics on a fresh VM); an empty slice becomes an empty list (the schema's Default value when the user omits the attribute).
func HardDiskDriveListFromSlice ¶ added in v0.5.0
func HardDiskDriveListFromSlice(ctx context.Context, slice []HardDiskDriveModel) (types.List, diag.Diagnostics)
HardDiskDriveListFromSlice builds a types.List from a slice; nil -> null, empty -> empty.
func NetworkAdapterListFromSlice ¶ added in v0.5.0
func NetworkAdapterListFromSlice(ctx context.Context, slice []NetworkAdapterModel) (types.List, diag.Diagnostics)
NetworkAdapterListFromSlice builds a types.List from a slice; nil -> null, empty -> empty.
Types ¶
type BootOrderEntryModel ¶
type BootOrderEntryModel struct {
Type types.String `tfsdk:"type"`
ControllerType types.String `tfsdk:"controller_type"`
ControllerNumber types.Int64 `tfsdk:"controller_number"`
ControllerLocation types.Int64 `tfsdk:"controller_location"`
Name types.String `tfsdk:"name"`
}
BootOrderEntryModel is one element of the `boot_order` list on a gen 2 hyperv_vm. Type discriminates between hard_disk_drive / dvd_drive entries, which carry the slot tuple, and network_adapter entries, which carry Name; unused fields for a given Type are null. Gen 1 BIOS startup order is a separate, deferred slice, and the schema validator rejects boot_order on gen 1 at plan time.
type CPUModel ¶
CPUModel is the nested `cpu` block. Static count only in this slice; dynamic-CPU attributes (weight, reserve, limit) attach as additional fields here in a follow-up.
type DvdDriveModel ¶
type DvdDriveModel struct {
IsoPath pathtype.Path `tfsdk:"iso_path"`
ControllerType types.String `tfsdk:"controller_type"`
ControllerNumber types.Int64 `tfsdk:"controller_number"`
ControllerLocation types.Int64 `tfsdk:"controller_location"`
}
DvdDriveModel is one element of the `dvd_drive` list on hyperv_vm. Same slot tuple as HardDiskDriveModel (controller_type, controller_number, controller_location), but IsoPath is Optional -- an empty DVD drive (no medium loaded) is a legitimate config.
type HardDiskDriveModel ¶
type HardDiskDriveModel struct {
Path pathtype.Path `tfsdk:"path"`
ControllerType types.String `tfsdk:"controller_type"`
ControllerNumber types.Int64 `tfsdk:"controller_number"`
ControllerLocation types.Int64 `tfsdk:"controller_location"`
}
HardDiskDriveModel is one element of the `hard_disk_drive` nested set on hyperv_vm, identifying an attached VHD (Path) at a specific controller slot (ControllerType + ControllerNumber + ControllerLocation). Path uses pathtype.Path for slash/case folding consistent with hyperv_vhd.path and hyperv_image_file.destination_path, so a forward-slash path round-trips against the bench's canonical backslash form without phantom diffs.
type MemoryModel ¶
type MemoryModel struct {
StartupBytes types.Int64 `tfsdk:"startup_bytes"`
Dynamic types.Bool `tfsdk:"dynamic"`
MinBytes types.Int64 `tfsdk:"min_bytes"`
MaxBytes types.Int64 `tfsdk:"max_bytes"`
}
MemoryModel is the nested `memory` block. StartupBytes is required; Dynamic / MinBytes / MaxBytes opt in to Hyper-V's dynamic memory mode, following the same Optional+Computed+UseStateForUnknown pattern as state.shutdown_mode. Buffer and Priority are deferred.
type Model ¶
type Model struct {
ID types.String `tfsdk:"id"`
VMID types.String `tfsdk:"vm_id"`
Name types.String `tfsdk:"name"`
Generation types.Int64 `tfsdk:"generation"`
// CPU and Memory are pointer-typed: ImportState briefly leaves state with only `name` set, which a value type can't represent.
CPU *CPUModel `tfsdk:"cpu"`
Memory *MemoryModel `tfsdk:"memory"`
// HardDiskDrives is types.List, not []Struct, so an unknown plan
// value decodes cleanly; List instead of Set works around a
// terraform-plugin-framework v1.19 reflect-decode error on nested-set slices.
HardDiskDrives types.List `tfsdk:"hard_disk_drive"`
NetworkAdapters types.List `tfsdk:"network_adapter"`
DvdDrives types.List `tfsdk:"dvd_drive"`
BootOrder types.List `tfsdk:"boot_order"`
// SecureBoot is types.Bool, not *bool: null cleanly represents a gen-1 host with no Secure Boot concept.
SecureBoot types.Bool `tfsdk:"secure_boot"`
SecureBootTemplate types.String `tfsdk:"secure_boot_template"`
Notes types.String `tfsdk:"notes"`
State *StateModel `tfsdk:"state"`
IPAddresses types.List `tfsdk:"ip_addresses"`
Path types.String `tfsdk:"path"`
}
Model is the tfsdk-bound struct backing the resource state. Field tags align with schema.go attribute names; conversion to/from the typed hyperv.VM DTO lives in resource.go.
func (*Model) BootOrderEntries ¶ added in v0.3.0
func (m *Model) BootOrderEntries(ctx context.Context) ([]BootOrderEntryModel, diag.Diagnostics)
BootOrderEntries returns the typed slice underlying m.BootOrder, or nil if null/unknown. Same null-vs-empty rationale as DvdDriveModels.
func (*Model) DvdDriveModels ¶ added in v0.3.0
func (m *Model) DvdDriveModels(ctx context.Context) ([]DvdDriveModel, diag.Diagnostics)
DvdDriveModels returns the typed slice underlying m.DvdDrives, or nil if the list is null or unknown. Resource code that needs to distinguish "user explicitly set []" from "user did not set the attribute" should inspect m.DvdDrives directly via IsNull / IsUnknown -- a known-empty list returns an empty (but non-nil) slice here.
func (*Model) HardDiskDriveModels ¶ added in v0.5.0
func (m *Model) HardDiskDriveModels(ctx context.Context) ([]HardDiskDriveModel, diag.Diagnostics)
HardDiskDriveModels decodes m.HardDiskDrives, or nil if null/unknown.
func (*Model) NetworkAdapterModels ¶ added in v0.5.0
func (m *Model) NetworkAdapterModels(ctx context.Context) ([]NetworkAdapterModel, diag.Diagnostics)
NetworkAdapterModels decodes m.NetworkAdapters, or nil if null/unknown.
type NetworkAdapterModel ¶
type NetworkAdapterModel struct {
// Name is the slot key for diff/reconciliation; the schema validator enforces uniqueness within a VM's list at plan time.
Name types.String `tfsdk:"name"`
SwitchName types.String `tfsdk:"switch_name"`
// IPAddresses is Computed from the host, giving a multi-homed VM a per-NIC view distinct from the VM-level ip_addresses list.
IPAddresses types.List `tfsdk:"ip_addresses"`
// MacAddress is Optional, not Computed: Computed would mask an intentional revert to dynamic-MAC mode by copying state forward.
MacAddress mactype.MAC `tfsdk:"mac_address"`
// VlanID is Optional, not Computed, for the same reason as MacAddress; unset means untagged, not "not yet read."
VlanID types.Int64 `tfsdk:"vlan_id"`
}
NetworkAdapterModel is one element of the `network_adapter` list on hyperv_vm.
type Resource ¶
type Resource struct {
// contains filtered or unexported fields
}
Resource implements hyperv_vm.
func (*Resource) ConfigValidators ¶
func (r *Resource) ConfigValidators(_ context.Context) []resource.ConfigValidator
ConfigValidators rejects mode/attribute combinations at plan time so the operator gets a clear, attribute-anchored diagnostic instead of the cmdlet's opaque error at apply time.
func (*Resource) Configure ¶
func (r *Resource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse)
Configure stashes the typed Hyper-V client built by the provider's Configure pass. Skips when ProviderData is nil (validate-time invocation before the provider has resolved its config).
func (*Resource) Create ¶
func (r *Resource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse)
Create runs new.ps1 with the plan's attributes and writes the post-create read back to state.
func (*Resource) Delete ¶
func (r *Resource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse)
Delete runs remove.ps1. ErrNotFound is treated as success (the VM is already gone). The script hard-stops the VM first if it's running -- this is the one place the PS layer drives a power transition. Hard stop (Stop-VM -Force -TurnOff) instead of graceful for the reasons documented in the resource MarkdownDescription: graceful shutdown hangs indefinitely on guests with absent / unresponsive integration services, and destroy semantics across IaC providers consistently match the "destroy means destroy" expectation.
func (*Resource) ImportState ¶
func (r *Resource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse)
ImportState lets `terraform import hyperv_vm.foo my-vm` work by treating the import ID as the VM name. Read populates the rest of the attributes via Get-VM on the immediately-following refresh.
func (*Resource) Metadata ¶
func (r *Resource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse)
Metadata sets the resource's TF type name.
func (*Resource) Read ¶
func (r *Resource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse)
Read fetches the current state via get.ps1 and reconciles it: ErrNotFound triggers RemoveResource so Terraform plans recreate; other errors call AddError so a transient fault doesn't silently drop the resource from state.
func (*Resource) Schema ¶
func (r *Resource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse)
Schema returns the locked-in schema (see schema.go).
func (*Resource) Update ¶
func (r *Resource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse)
Update forwards only the fields that changed between state and plan to avoid hitting Set-VMMemory / Set-VMProcessor needlessly on a running VM (those cmdlets validate state by parameter set, not value semantics -- even a no-op call to Set-VMMemory on a running VM errors). Generation is always forwarded as the script's gen-2-only SecureBoot guard hint.
func (*Resource) UpgradeState ¶
UpgradeState bridges schema versions for hyperv_vm. Each entry maps from a SOURCE version directly to the current schema; the framework dispatches based on the on-disk version, not a chain, so each upgradeNToM helper returns the current Model in one hop. When a new schema version lands, add a new priorSchemaVX / priorModelVX / upgradeVXToV(X+1) triple here and update the existing helpers to populate any new fields.
type StateModel ¶
type StateModel struct {
Desired types.String `tfsdk:"desired"`
Current types.String `tfsdk:"current"`
ShutdownMode types.String `tfsdk:"shutdown_mode"`
}
StateModel is the nested `state` block on hyperv_vm. Pointer-typed for the same reason as CPU and Memory. Desired is the user-facing power-state input ("Off" | "Running"), a transition fires only when it differs from the host's actual state, and Current is the Computed readback from Hyper-V.