diff --git a/.github/auto-label.yaml b/.github/auto-label.yaml index 24c28d84..3e5b3162 100644 --- a/.github/auto-label.yaml +++ b/.github/auto-label.yaml @@ -7,4 +7,4 @@ staleness: path: pullrequest: true paths: - .: 'docs' + docs: 'documentation' diff --git a/docs/resources/virtual_environment_vm.md b/docs/resources/virtual_environment_vm.md index 1c621365..c220b150 100644 --- a/docs/resources/virtual_environment_vm.md +++ b/docs/resources/virtual_environment_vm.md @@ -216,6 +216,7 @@ output "ubuntu_vm_public_key" { * `username` - (Optional) The SSH username. * `user_data_file_id` - (Optional) The identifier for a file containing custom user data (conflicts with `user_account`). + * `vendor_data_file_id` - (Optional) The identifier for a file containing all vendor data passed to the VM via cloud-init. * `keyboard_layout` - (Optional) The keyboard layout (defaults to `en-us`). * `da` - Danish. * `de` - German. diff --git a/example/resource_virtual_environment_file.tf b/example/resource_virtual_environment_file.tf index 18fc37bd..7239241a 100644 --- a/example/resource_virtual_environment_file.tf +++ b/example/resource_virtual_environment_file.tf @@ -2,7 +2,7 @@ # Cloud Config (cloud-init) #=============================================================================== -resource "proxmox_virtual_environment_file" "cloud_config" { +resource "proxmox_virtual_environment_file" "user_config" { content_type = "snippets" datastore_id = element(data.proxmox_virtual_environment_datastores.example.datastore_ids, index(data.proxmox_virtual_environment_datastores.example.datastore_ids, "local")) node_name = data.proxmox_virtual_environment_datastores.example.node_name @@ -15,8 +15,6 @@ chpasswd: ubuntu:example expire: false hostname: terraform-provider-proxmox-example -packages: - - qemu-guest-agent users: - default - name: ubuntu @@ -27,10 +25,31 @@ users: sudo: ALL=(ALL) NOPASSWD:ALL EOF - file_name = "terraform-provider-proxmox-example-cloud-config.yaml" + file_name = "terraform-provider-proxmox-example-user-config.yaml" } } +resource "proxmox_virtual_environment_file" "vendor_config" { + content_type = "snippets" + datastore_id = element(data.proxmox_virtual_environment_datastores.example.datastore_ids, index(data.proxmox_virtual_environment_datastores.example.datastore_ids, "local")) + node_name = data.proxmox_virtual_environment_datastores.example.node_name + + source_raw { + data = < /tmp/vendor-cloud-init-done + EOF + + file_name = "terraform-provider-proxmox-example-vendor-config.yaml" + } +} + + #=============================================================================== # Ubuntu Cloud Image #=============================================================================== diff --git a/example/resource_virtual_environment_vm.tf b/example/resource_virtual_environment_vm.tf index fc99e45f..01cab3ab 100644 --- a/example/resource_virtual_environment_vm.tf +++ b/example/resource_virtual_environment_vm.tf @@ -8,7 +8,7 @@ resource "proxmox_virtual_environment_vm" "example_template" { disk { datastore_id = element(data.proxmox_virtual_environment_datastores.example.datastore_ids, index(data.proxmox_virtual_environment_datastores.example.datastore_ids, "local-lvm")) file_id = proxmox_virtual_environment_file.ubuntu_cloud_image.id - interface = "scsi0" + interface = "virtio0" discard = "on" iothread = true } @@ -17,7 +17,6 @@ resource "proxmox_virtual_environment_vm" "example_template" { # datastore_id = "nfs" # interface = "scsi1" # discard = "ignore" -# iothread = true # file_format = "raw" # } @@ -34,13 +33,8 @@ resource "proxmox_virtual_environment_vm" "example_template" { } } - user_account { - keys = [trimspace(tls_private_key.example.public_key_openssh)] - password = "example" - username = "ubuntu" - } - - user_data_file_id = proxmox_virtual_environment_file.cloud_config.id + user_data_file_id = proxmox_virtual_environment_file.user_config.id + vendor_data_file_id = proxmox_virtual_environment_file.vendor_config.id } name = "terraform-provider-proxmox-example-template" diff --git a/main.go b/main.go index c8527199..8320a40c 100644 --- a/main.go +++ b/main.go @@ -19,7 +19,7 @@ func main() { opts := &plugin.ServeOpts{ Debug: debug, - ProviderAddr: "registry.terraform.io/bpg/terraform", + ProviderAddr: "registry.terraform.io/bpg/proxmox", ProviderFunc: func() *schema.Provider { return proxmoxtf.Provider() }, diff --git a/proxmox/virtual_environment_vm_types.go b/proxmox/virtual_environment_vm_types.go index 7143275c..2bbeb54a 100644 --- a/proxmox/virtual_environment_vm_types.go +++ b/proxmox/virtual_environment_vm_types.go @@ -48,6 +48,7 @@ type CustomCloudInitFiles struct { MetaVolume *string `json:"meta,omitempty" url:"meta,omitempty"` NetworkVolume *string `json:"network,omitempty" url:"network,omitempty"` UserVolume *string `json:"user,omitempty" url:"user,omitempty"` + VendorVolume *string `json:"vendor,omitempty" url:"vendor,omitempty"` } // CustomCloudInitIPConfig handles QEMU cloud-init IP configuration parameters. @@ -221,7 +222,7 @@ type VirtualEnvironmentVMCloneRequestBody struct { VMIDNew int `json:"newid" url:"newid"` } -// VirtualEnvironmentVMCreateRequestBody contains the data for an virtual machine create request. +// VirtualEnvironmentVMCreateRequestBody contains the data for a virtual machine create request. type VirtualEnvironmentVMCreateRequestBody struct { ACPI *CustomBool `json:"acpi,omitempty" url:"acpi,omitempty,int"` Agent *CustomAgent `json:"agent,omitempty" url:"agent,omitempty"` @@ -623,7 +624,7 @@ func (r CustomAudioDevices) EncodeValues(key string, v *url.Values) error { return nil } -// EncodeValues converts a CustomCloudInitConfig struct to multiple URL vlaues. +// EncodeValues converts a CustomCloudInitConfig struct to multiple URL values. func (r CustomCloudInitConfig) EncodeValues(_ string, v *url.Values) error { if r.Files != nil { var volumes []string @@ -640,6 +641,10 @@ func (r CustomCloudInitConfig) EncodeValues(_ string, v *url.Values) error { volumes = append(volumes, fmt.Sprintf("user=%s", *r.Files.UserVolume)) } + if r.Files.VendorVolume != nil { + volumes = append(volumes, fmt.Sprintf("vendor=%s", *r.Files.VendorVolume)) + } + if len(volumes) > 0 { v.Add("cicustom", strings.Join(volumes, ",")) } @@ -1279,6 +1284,8 @@ func (r *CustomCloudInitFiles) UnmarshalJSON(b []byte) error { r.MetaVolume = &v[1] case "user": r.UserVolume = &v[1] + case "vendor": + r.VendorVolume = &v[1] } } } diff --git a/proxmoxtf/resource_virtual_environment_vm.go b/proxmoxtf/resource_virtual_environment_vm.go index efd4c477..1c682393 100644 --- a/proxmoxtf/resource_virtual_environment_vm.go +++ b/proxmoxtf/resource_virtual_environment_vm.go @@ -65,6 +65,7 @@ const ( dvResourceVirtualEnvironmentVMInitializationIPConfigIPv6Gateway = "" dvResourceVirtualEnvironmentVMInitializationUserAccountPassword = "" dvResourceVirtualEnvironmentVMInitializationUserDataFileID = "" + dvResourceVirtualEnvironmentVMInitializationVendorDataFileID = "" dvResourceVirtualEnvironmentVMInitializationType = "" dvResourceVirtualEnvironmentVMKeyboardLayout = "en-us" dvResourceVirtualEnvironmentVMMemoryDedicated = 512 @@ -160,6 +161,7 @@ const ( mkResourceVirtualEnvironmentVMInitializationUserAccountPassword = "password" mkResourceVirtualEnvironmentVMInitializationUserAccountUsername = "username" mkResourceVirtualEnvironmentVMInitializationUserDataFileID = "user_data_file_id" + mkResourceVirtualEnvironmentVMInitializationVendorDataFileID = "vendor_data_file_id" mkResourceVirtualEnvironmentVMIPv4Addresses = "ipv4_addresses" mkResourceVirtualEnvironmentVMIPv6Addresses = "ipv6_addresses" mkResourceVirtualEnvironmentVMKeyboardLayout = "keyboard_layout" @@ -741,6 +743,14 @@ func resourceVirtualEnvironmentVM() *schema.Resource { Default: dvResourceVirtualEnvironmentVMInitializationUserDataFileID, ValidateDiagFunc: getFileIDValidator(), }, + mkResourceVirtualEnvironmentVMInitializationVendorDataFileID: { + Type: schema.TypeString, + Description: "The ID of a file containing vendor data", + Optional: true, + ForceNew: true, + Default: dvResourceVirtualEnvironmentVMInitializationVendorDataFileID, + ValidateDiagFunc: getFileIDValidator(), + }, mkResourceVirtualEnvironmentVMInitializationType: { Type: schema.TypeString, Description: "The cloud-init configuration format", @@ -2087,6 +2097,15 @@ func resourceVirtualEnvironmentVMGetCloudInitConfig(d *schema.ResourceData) (*pr } } + initializationVendorDataFileID := initializationBlock[mkResourceVirtualEnvironmentVMInitializationVendorDataFileID].(string) + + if initializationVendorDataFileID != "" { + if initializationConfig.Files == nil { + initializationConfig.Files = &proxmox.CustomCloudInitFiles{} + } + initializationConfig.Files.VendorVolume = &initializationVendorDataFileID + } + initializationType := initializationBlock[mkResourceVirtualEnvironmentVMInitializationType].(string) if initializationType != "" { @@ -2817,8 +2836,14 @@ func resourceVirtualEnvironmentVMReadCustom(ctx context.Context, d *schema.Resou } else { initialization[mkResourceVirtualEnvironmentVMInitializationUserDataFileID] = "" } + if vmConfig.CloudInitFiles.VendorVolume != nil { + initialization[mkResourceVirtualEnvironmentVMInitializationVendorDataFileID] = *vmConfig.CloudInitFiles.VendorVolume + } else { + initialization[mkResourceVirtualEnvironmentVMInitializationVendorDataFileID] = "" + } } else if len(initialization) > 0 { initialization[mkResourceVirtualEnvironmentVMInitializationUserDataFileID] = "" + initialization[mkResourceVirtualEnvironmentVMInitializationVendorDataFileID] = "" } if vmConfig.CloudInitType != nil {