mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-07-02 03:22:59 +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:
parent
bfdc61e06b
commit
9e34dfb362
2
.github/auto-label.yaml
vendored
2
.github/auto-label.yaml
vendored
@ -7,4 +7,4 @@ staleness:
|
|||||||
path:
|
path:
|
||||||
pullrequest: true
|
pullrequest: true
|
||||||
paths:
|
paths:
|
||||||
.: 'docs'
|
docs: 'documentation'
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
@ -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"
|
||||||
|
2
main.go
2
main.go
@ -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()
|
||||||
},
|
},
|
||||||
|
@ -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]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user