0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-07-02 19:43:00 +00:00

feat: Add support for custom cloud-init vendor data file (#162)

* feat: Add support for custom cloud-init vendor data file

Add new argument `initialization`.`vendor_data_file_id` to specify a file ID form snippets.

* add vendor cloud-init to examples

* add missing `vendor` to unmarshal

* remove debug lines
This commit is contained in:
Pavel Boldyrev 2022-11-17 20:33:41 -05:00 committed by GitHub
parent bfdc61e06b
commit 9e34dfb362
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 17 deletions

View File

@ -7,4 +7,4 @@ staleness:
path: path:
pullrequest: true pullrequest: true
paths: paths:
.: 'docs' docs: 'documentation'

View File

@ -216,6 +216,7 @@ output "ubuntu_vm_public_key" {
* `username` - (Optional) The SSH username. * `username` - (Optional) The SSH username.
* `user_data_file_id` - (Optional) The identifier for a file containing custom user data (conflicts * `user_data_file_id` - (Optional) The identifier for a file containing custom user data (conflicts
with `user_account`). 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`). * `keyboard_layout` - (Optional) The keyboard layout (defaults to `en-us`).
* `da` - Danish. * `da` - Danish.
* `de` - German. * `de` - German.

View File

@ -2,7 +2,7 @@
# Cloud Config (cloud-init) # Cloud Config (cloud-init)
#=============================================================================== #===============================================================================
resource "proxmox_virtual_environment_file" "cloud_config" { resource "proxmox_virtual_environment_file" "user_config" {
content_type = "snippets" content_type = "snippets"
datastore_id = element(data.proxmox_virtual_environment_datastores.example.datastore_ids, index(data.proxmox_virtual_environment_datastores.example.datastore_ids, "local")) 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 node_name = data.proxmox_virtual_environment_datastores.example.node_name
@ -15,8 +15,6 @@ chpasswd:
ubuntu:example ubuntu:example
expire: false expire: false
hostname: terraform-provider-proxmox-example hostname: terraform-provider-proxmox-example
packages:
- qemu-guest-agent
users: users:
- default - default
- name: ubuntu - name: ubuntu
@ -27,10 +25,31 @@ users:
sudo: ALL=(ALL) NOPASSWD:ALL sudo: ALL=(ALL) NOPASSWD:ALL
EOF 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 = <<EOF
#cloud-config
runcmd:
- apt update
- apt install -y qemu-guest-agent
- systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent
- echo "done" > /tmp/vendor-cloud-init-done
EOF
file_name = "terraform-provider-proxmox-example-vendor-config.yaml"
}
}
#=============================================================================== #===============================================================================
# Ubuntu Cloud Image # Ubuntu Cloud Image
#=============================================================================== #===============================================================================

View File

@ -8,7 +8,7 @@ resource "proxmox_virtual_environment_vm" "example_template" {
disk { disk {
datastore_id = element(data.proxmox_virtual_environment_datastores.example.datastore_ids, index(data.proxmox_virtual_environment_datastores.example.datastore_ids, "local-lvm")) 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 file_id = proxmox_virtual_environment_file.ubuntu_cloud_image.id
interface = "scsi0" interface = "virtio0"
discard = "on" discard = "on"
iothread = true iothread = true
} }
@ -17,7 +17,6 @@ resource "proxmox_virtual_environment_vm" "example_template" {
# datastore_id = "nfs" # datastore_id = "nfs"
# interface = "scsi1" # interface = "scsi1"
# discard = "ignore" # discard = "ignore"
# iothread = true
# file_format = "raw" # file_format = "raw"
# } # }
@ -34,13 +33,8 @@ resource "proxmox_virtual_environment_vm" "example_template" {
} }
} }
user_account { user_data_file_id = proxmox_virtual_environment_file.user_config.id
keys = [trimspace(tls_private_key.example.public_key_openssh)] vendor_data_file_id = proxmox_virtual_environment_file.vendor_config.id
password = "example"
username = "ubuntu"
}
user_data_file_id = proxmox_virtual_environment_file.cloud_config.id
} }
name = "terraform-provider-proxmox-example-template" name = "terraform-provider-proxmox-example-template"

View File

@ -19,7 +19,7 @@ func main() {
opts := &plugin.ServeOpts{ opts := &plugin.ServeOpts{
Debug: debug, Debug: debug,
ProviderAddr: "registry.terraform.io/bpg/terraform", ProviderAddr: "registry.terraform.io/bpg/proxmox",
ProviderFunc: func() *schema.Provider { ProviderFunc: func() *schema.Provider {
return proxmoxtf.Provider() return proxmoxtf.Provider()
}, },

View File

@ -48,6 +48,7 @@ type CustomCloudInitFiles struct {
MetaVolume *string `json:"meta,omitempty" url:"meta,omitempty"` MetaVolume *string `json:"meta,omitempty" url:"meta,omitempty"`
NetworkVolume *string `json:"network,omitempty" url:"network,omitempty"` NetworkVolume *string `json:"network,omitempty" url:"network,omitempty"`
UserVolume *string `json:"user,omitempty" url:"user,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. // CustomCloudInitIPConfig handles QEMU cloud-init IP configuration parameters.
@ -221,7 +222,7 @@ type VirtualEnvironmentVMCloneRequestBody struct {
VMIDNew int `json:"newid" url:"newid"` 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 { type VirtualEnvironmentVMCreateRequestBody struct {
ACPI *CustomBool `json:"acpi,omitempty" url:"acpi,omitempty,int"` ACPI *CustomBool `json:"acpi,omitempty" url:"acpi,omitempty,int"`
Agent *CustomAgent `json:"agent,omitempty" url:"agent,omitempty"` Agent *CustomAgent `json:"agent,omitempty" url:"agent,omitempty"`
@ -623,7 +624,7 @@ func (r CustomAudioDevices) EncodeValues(key string, v *url.Values) error {
return nil 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 { func (r CustomCloudInitConfig) EncodeValues(_ string, v *url.Values) error {
if r.Files != nil { if r.Files != nil {
var volumes []string 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)) 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 { if len(volumes) > 0 {
v.Add("cicustom", strings.Join(volumes, ",")) v.Add("cicustom", strings.Join(volumes, ","))
} }
@ -1279,6 +1284,8 @@ func (r *CustomCloudInitFiles) UnmarshalJSON(b []byte) error {
r.MetaVolume = &v[1] r.MetaVolume = &v[1]
case "user": case "user":
r.UserVolume = &v[1] r.UserVolume = &v[1]
case "vendor":
r.VendorVolume = &v[1]
} }
} }
} }

View File

@ -65,6 +65,7 @@ const (
dvResourceVirtualEnvironmentVMInitializationIPConfigIPv6Gateway = "" dvResourceVirtualEnvironmentVMInitializationIPConfigIPv6Gateway = ""
dvResourceVirtualEnvironmentVMInitializationUserAccountPassword = "" dvResourceVirtualEnvironmentVMInitializationUserAccountPassword = ""
dvResourceVirtualEnvironmentVMInitializationUserDataFileID = "" dvResourceVirtualEnvironmentVMInitializationUserDataFileID = ""
dvResourceVirtualEnvironmentVMInitializationVendorDataFileID = ""
dvResourceVirtualEnvironmentVMInitializationType = "" dvResourceVirtualEnvironmentVMInitializationType = ""
dvResourceVirtualEnvironmentVMKeyboardLayout = "en-us" dvResourceVirtualEnvironmentVMKeyboardLayout = "en-us"
dvResourceVirtualEnvironmentVMMemoryDedicated = 512 dvResourceVirtualEnvironmentVMMemoryDedicated = 512
@ -160,6 +161,7 @@ const (
mkResourceVirtualEnvironmentVMInitializationUserAccountPassword = "password" mkResourceVirtualEnvironmentVMInitializationUserAccountPassword = "password"
mkResourceVirtualEnvironmentVMInitializationUserAccountUsername = "username" mkResourceVirtualEnvironmentVMInitializationUserAccountUsername = "username"
mkResourceVirtualEnvironmentVMInitializationUserDataFileID = "user_data_file_id" mkResourceVirtualEnvironmentVMInitializationUserDataFileID = "user_data_file_id"
mkResourceVirtualEnvironmentVMInitializationVendorDataFileID = "vendor_data_file_id"
mkResourceVirtualEnvironmentVMIPv4Addresses = "ipv4_addresses" mkResourceVirtualEnvironmentVMIPv4Addresses = "ipv4_addresses"
mkResourceVirtualEnvironmentVMIPv6Addresses = "ipv6_addresses" mkResourceVirtualEnvironmentVMIPv6Addresses = "ipv6_addresses"
mkResourceVirtualEnvironmentVMKeyboardLayout = "keyboard_layout" mkResourceVirtualEnvironmentVMKeyboardLayout = "keyboard_layout"
@ -741,6 +743,14 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
Default: dvResourceVirtualEnvironmentVMInitializationUserDataFileID, Default: dvResourceVirtualEnvironmentVMInitializationUserDataFileID,
ValidateDiagFunc: getFileIDValidator(), ValidateDiagFunc: getFileIDValidator(),
}, },
mkResourceVirtualEnvironmentVMInitializationVendorDataFileID: {
Type: schema.TypeString,
Description: "The ID of a file containing vendor data",
Optional: true,
ForceNew: true,
Default: dvResourceVirtualEnvironmentVMInitializationVendorDataFileID,
ValidateDiagFunc: getFileIDValidator(),
},
mkResourceVirtualEnvironmentVMInitializationType: { mkResourceVirtualEnvironmentVMInitializationType: {
Type: schema.TypeString, Type: schema.TypeString,
Description: "The cloud-init configuration format", 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) initializationType := initializationBlock[mkResourceVirtualEnvironmentVMInitializationType].(string)
if initializationType != "" { if initializationType != "" {
@ -2817,8 +2836,14 @@ func resourceVirtualEnvironmentVMReadCustom(ctx context.Context, d *schema.Resou
} else { } else {
initialization[mkResourceVirtualEnvironmentVMInitializationUserDataFileID] = "" initialization[mkResourceVirtualEnvironmentVMInitializationUserDataFileID] = ""
} }
if vmConfig.CloudInitFiles.VendorVolume != nil {
initialization[mkResourceVirtualEnvironmentVMInitializationVendorDataFileID] = *vmConfig.CloudInitFiles.VendorVolume
} else {
initialization[mkResourceVirtualEnvironmentVMInitializationVendorDataFileID] = ""
}
} else if len(initialization) > 0 { } else if len(initialization) > 0 {
initialization[mkResourceVirtualEnvironmentVMInitializationUserDataFileID] = "" initialization[mkResourceVirtualEnvironmentVMInitializationUserDataFileID] = ""
initialization[mkResourceVirtualEnvironmentVMInitializationVendorDataFileID] = ""
} }
if vmConfig.CloudInitType != nil { if vmConfig.CloudInitType != nil {