bpg / terraform-provider-proxmox

Terraform Provider for Proxmox
https://registry.terraform.io/providers/bpg/proxmox
Mozilla Public License 2.0
752 stars 125 forks source link

proxmox_virtual_environment_vm forces replacement by unchanged initialization.user_account.keys #1443

Open charles-low opened 1 month ago

charles-low commented 1 month ago

Describe the bug The terraform reported that the vm required to be replaced because the initialization.user_account.keys has changed. However the key didn't change, the terraform plan shows the following output

          ~ user_account {
              ~ keys     = [ # forces replacement
                  - "ssh-ed25519 AAAACbla bla bla bla",
                  + <<-EOT
                        ssh-ed25519 AAAACbla bla bla bla
                    EOT,
                ]
              ~ password = (sensitive value)
                # (1 unchanged attribute hidden)
            }

To Reproduce

  1. Create a vm with initialization block that include user_account and ssh pubkey in an array.
  2. Apply twice, the second time will state that the vm need to be replaced due to the keys is different.

Please also provide a minimal Terraform configuration that reproduces the issue.

resource "proxmox_virtual_environment_vm" "elasticsearch" {
    for_each = local.instances

    name                    = each.value.name
    pool_id                 = each.value.pool_id
    node_name               = each.value.node_name
    description             = "Managed by Terraform - ElasticSearch 01"
    tags                    = ["elasticsearch","terraform","ubuntu","24.04","cloud-init"]

        user_account {
          username = "admin"
          password = random_password.passwords[each.key].bcrypt_hash
          keys = [ file("~/.ssh/id_ed25519.pub") ]
       }
}

Expected behavior The vm should stay intact.

bpg commented 1 month ago

Hi @charles-low šŸ‘‹šŸ¼

I can't reproduce the issue with this template:

resource "proxmox_virtual_environment_vm" "test_vm_cloudinit" {
    node_name = "pve"
    started   = false
    agent {
        enabled = true
    }
    cpu {
        cores = 2
    }
    memory {
        dedicated = 2048
    }
    disk {
        datastore_id = "local-lvm"
        file_id      = proxmox_virtual_environment_download_file.ubuntu_cloud_image.id
        interface    = "virtio0"
        iothread     = true
        discard      = "on"
        size         = 20
    }

    initialization {
        user_account {
            username = "ubuntu"
            keys     = [
                "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOQCHPhOV9XsJa3uq4bmKymklNy6ktgBB/+2umizgnnY",
            ]
        }
        ip_config {
            ipv4 {
                address = "dhcp"
            }
        }
    }
    network_device {
        bridge = "vmbr0"
    }
}

It looks like the key in your case has changed from a single line to a heredoc-style with leading spaces:

<<-EOT
    ssh-ed25519 AAAACbla bla bla bla
EOT,

From Terraform's perspective, this is a value change, even though the significant string has not changed.

bpg commented 1 month ago

Hi @charles-low šŸ‘‹šŸ¼

It looks like the key in your case has changed from a single line to a heredoc-style with leading space

Have you had a chance to double check that? Is your issue still reproducible?

gustavodrodriguez commented 2 weeks ago

Hi @charles-low

Have you tried using the character clearing function so that you don't have to destroy the VM?

keys        = [trimspace(var.ci_sshkey)]

or in you case:

keys = [ trimspace(file("~/.ssh/id_ed25519.pub")) ]

Example for dynamic

    dynamic "initialization" {
                for_each = var.vm_enable_cloudinit ? [1] : []
                content {
            datastore_id    = var.disk_storage
            interface   = var.ci_interface
            ip_config {
                ipv4 {
                    address = var.ci_ipv4_address
                    gateway = var.ci_ipv4_address == "dhcp" ? null : var.ci_gateway
                }
            }
            user_account {
                username    = var.ci_user
                keys        = [trimspace(var.ci_sshkey)]
            }
            dns {
                domain      = var.ci_dns_domain
                servers     = [trimspace(var.ci_dns_servers)]
            }
        }
    }