diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a348f16..0000000 --- a/.gitignore +++ /dev/null @@ -1,83 +0,0 @@ -# ---> Terraform -# Local .terraform directories -**/.terraform/* - -# .tfstate files -*.tfstate -*.tfstate.* - -# Crash log files -crash.log -crash.*.log - -# Exclude all .tfvars files, which are likely to contain sensitive data, such as -# password, private keys, and other secrets. These should not be part of version -# control as they are data points which are potentially sensitive and subject -# to change depending on the environment. -*.tfvars -*.tfvars.json - -# Ignore override files as they are usually used to override resources locally and so -# are not checked in -override.tf -override.tf.json -*_override.tf -*_override.tf.json - -# Ignore transient lock info files created by terraform apply -.terraform.tfstate.lock.info - -# Include override files you do wish to add to version control using negated pattern -# !example_override.tf - -# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan -# example: *tfplan* - -# Ignore CLI configuration files -.terraformrc -terraform.rc - -# ---> OpenTofu -# Local .terraform directories -**/.terraform/* - -# .tfstate files -*.tfstate -*.tfstate.* - -# Crash log files -crash.log -crash.*.log - -# Exclude all .tfvars files, which are likely to contain sensitive data, such as -# password, private keys, and other secrets. These should not be part of version -# control as they are data points which are potentially sensitive and subject -# to change depending on the environment. -*.tfvars -*.tfvars.json - -# Ignore override files as they are usually used to override resources locally and so -# are not checked in -override.tf -override.tofu -override.tf.json -override.tofu.json -*_override.tf -*_override.tofu -*_override.tf.json -*_override.tofu.json - -# Ignore transient lock info files created by tofu apply -.terraform.tfstate.lock.info - -# Include override files you do wish to add to version control using negated pattern -# !example_override.tf -# !example_override.tofu - -# Include tfplan files to ignore the plan output of command: tofu plan -out=tfplan -# example: *tfplan* - -# Ignore CLI configuration files -.terraformrc -terraform.rc - diff --git a/README.md b/README.md deleted file mode 100644 index f882b26..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# deploy-sandbox-vms - diff --git a/locals.tf b/locals.tf new file mode 100644 index 0000000..aae7eae --- /dev/null +++ b/locals.tf @@ -0,0 +1,19 @@ +locals { + # Alphabet pour la conversion base 26 des suffixes de noms de VMs. + letters = [ + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", + "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", + "u", "v", "w", "x", "y", "z" + ] + + # Dict des VMs a deployer, genere dynamiquement a partir de var.vm_count. + # cle = nom unique de la VM ex. "9999aaaa" + # value = parametres specifiques { vmid, ip } + vms = { + for i in range(var.vm_count) : + "9999aa${local.letters[floor(i / 26)]}${local.letters[i % 26]}" => { + vmid = 9010 + i + ip = cidrhost("10.1.90.0/24", 100 + i) + } + } +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..8eece42 --- /dev/null +++ b/main.tf @@ -0,0 +1,50 @@ +resource "proxmox_virtual_environment_vm" "lab" { + for_each = local.vms + + name = each.key + node_name = var.node_name + vm_id = each.value.vmid + + clone { + vm_id = var.template_id + full = true + } + + agent { + enabled = true + } + + cpu { + sockets = var.vm_cpu_sockets + cores = var.vm_cpu_cores + hotplugged = var.vm_cpu_hotplugged + } + + memory { + dedicated = var.vm_memory + } + + disk { + interface = "scsi0" + size = var.vm_disk_size + datastore_id = "local-lvm" + } + + network_device { + bridge = var.bridge + vlan_id = var.vlan_id + } + + initialization { + user_account { + username = var.ci_user + keys = [var.ssh_public_key] + } + ip_config { + ipv4 { + address = "${each.value.ip}/24" + gateway = var.gateway + } + } + } +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..3bfef95 --- /dev/null +++ b/outputs.tf @@ -0,0 +1,17 @@ +output "vm_names" { + description = "Liste des noms de VMs creees" + value = [for k, v in proxmox_virtual_environment_vm.lab : v.name] +} + +output "vm_ips" { + description = "Mapping nom de VM -> IP" + value = { for name, vm in local.vms : name => vm.ip } +} + +output "ssh_commands" { + description = "Commandes SSH pretes a copier pour chaque VM" + value = [ + for name, vm in local.vms : + "ssh ${var.ci_user}@${vm.ip} # ${name}" + ] +} diff --git a/providers.tf b/providers.tf new file mode 100644 index 0000000..c5772d7 --- /dev/null +++ b/providers.tf @@ -0,0 +1,5 @@ +provider "proxmox" { + endpoint = var.proxmox_endpoint + api_token = var.proxmox_api_token + insecure = var.proxmox_insecure +} diff --git a/terraform.tfstate b/terraform.tfstate new file mode 100644 index 0000000..68819c9 --- /dev/null +++ b/terraform.tfstate @@ -0,0 +1 @@ +{"version":4,"terraform_version":"1.11.5","serial":7,"lineage":"500c6307-1c37-d0cc-1c25-be2a978fbbbf","outputs":{},"resources":[],"check_results":[{"object_kind":"var","config_addr":"var.vm_count","status":"unknown","objects":null}]} diff --git a/terraform.tfstate.backup b/terraform.tfstate.backup new file mode 100644 index 0000000..bea21e1 --- /dev/null +++ b/terraform.tfstate.backup @@ -0,0 +1 @@ +{"version":4,"terraform_version":"1.11.5","serial":6,"lineage":"500c6307-1c37-d0cc-1c25-be2a978fbbbf","outputs":{"ssh_commands":{"value":["ssh nidoradmin@10.1.90.100 # 9999aaaa","ssh nidoradmin@10.1.90.101 # 9999aaab","ssh nidoradmin@10.1.90.102 # 9999aaac"],"type":["tuple",["string","string","string"]]},"vm_ips":{"value":{"9999aaaa":"10.1.90.100","9999aaab":"10.1.90.101","9999aaac":"10.1.90.102"},"type":["object",{"9999aaaa":"string","9999aaab":"string","9999aaac":"string"}]},"vm_names":{"value":["9999aaaa","9999aaab","9999aaac"],"type":["tuple",["string","string","string"]]}},"resources":[{"mode":"managed","type":"proxmox_virtual_environment_vm","name":"lab","provider":"provider[\"registry.opentofu.org/bpg/proxmox\"]","instances":[{"index_key":"9999aaaa","schema_version":0,"attributes":{"acpi":true,"agent":[{"enabled":true,"timeout":"15m","trim":false,"type":"virtio","wait_for_ip":[]}],"amd_sev":[],"audio_device":[],"bios":"seabios","boot_order":[],"cdrom":[],"clone":[{"datastore_id":"","full":true,"node_name":"","retries":1,"vm_id":100}],"cpu":[{"affinity":"","architecture":"","cores":12,"flags":null,"hotplugged":2,"limit":0,"numa":false,"sockets":1,"type":"qemu64","units":0}],"delete_unreferenced_disks_on_destroy":true,"description":null,"disk":[{"aio":"io_uring","backup":true,"cache":"none","datastore_id":"local-lvm","discard":"ignore","file_format":"raw","file_id":"","import_from":"","interface":"scsi0","iothread":false,"path_in_datastore":"vm-9010-disk-0","replicate":true,"serial":"","size":10,"speed":[],"ssd":false}],"efi_disk":[],"hook_script_file_id":null,"hostpci":[],"hotplug":null,"id":"9010","initialization":[{"datastore_id":"local-lvm","dns":[],"file_format":"","interface":"ide2","ip_config":[{"ipv4":[{"address":"10.1.90.100/24","gateway":"10.1.90.1"}],"ipv6":[]}],"meta_data_file_id":"","network_data_file_id":"","type":"","upgrade":true,"user_account":[{"keys":["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDV8PkUNKeIftHKf+nrS9CH9pUlOSJ8s27ejEgqH3kAs dorygann@fedora"],"password":"","username":"nidoradmin"}],"user_data_file_id":"","vendor_data_file_id":""}],"ipv4_addresses":[["127.0.0.1"],["10.1.90.100"]],"ipv6_addresses":[["::1"],["fe80::be24:11ff:fe35:3569"]],"keyboard_layout":"en-us","kvm_arguments":null,"mac_addresses":["00:00:00:00:00:00","BC:24:11:35:35:69"],"machine":null,"memory":[{"dedicated":1024,"floating":0,"hugepages":"","keep_hugepages":false,"shared":0}],"migrate":false,"name":"9999aaaa","network_device":[{"bridge":"vmbr0","disconnected":false,"enabled":true,"firewall":false,"mac_address":"BC:24:11:35:35:69","model":"virtio","mtu":0,"queues":0,"rate_limit":0,"trunks":"","vlan_id":90}],"network_interface_names":["lo","eth0"],"node_name":"npx-666942cd","numa":[],"on_boot":true,"operating_system":[],"pool_id":"","protection":false,"purge_on_destroy":true,"reboot":false,"reboot_after_update":true,"rng":[],"scsi_hardware":"virtio-scsi-pci","serial_device":[],"smbios":[],"started":true,"startup":[],"stop_on_destroy":false,"tablet_device":true,"tags":null,"template":false,"timeout_clone":1800,"timeout_create":1800,"timeout_migrate":1800,"timeout_move_disk":1800,"timeout_reboot":1800,"timeout_shutdown_vm":1800,"timeout_start_vm":1800,"timeout_stop_vm":300,"tpm_state":[],"usb":[],"vga":[],"virtiofs":[],"vm_id":9010,"watchdog":[]},"sensitive_attributes":[[{"type":"get_attr","value":"initialization"},{"type":"index","value":{"value":0,"type":"number"}},{"type":"get_attr","value":"user_account"},{"type":"index","value":{"value":0,"type":"number"}},{"type":"get_attr","value":"password"}]],"private":"bnVsbA=="},{"index_key":"9999aaab","schema_version":0,"attributes":{"acpi":true,"agent":[{"enabled":true,"timeout":"15m","trim":false,"type":"virtio","wait_for_ip":[]}],"amd_sev":[],"audio_device":[],"bios":"seabios","boot_order":[],"cdrom":[],"clone":[{"datastore_id":"","full":true,"node_name":"","retries":1,"vm_id":100}],"cpu":[{"affinity":"","architecture":"","cores":12,"flags":null,"hotplugged":2,"limit":0,"numa":false,"sockets":1,"type":"qemu64","units":0}],"delete_unreferenced_disks_on_destroy":true,"description":null,"disk":[{"aio":"io_uring","backup":true,"cache":"none","datastore_id":"local-lvm","discard":"ignore","file_format":"raw","file_id":"","import_from":"","interface":"scsi0","iothread":false,"path_in_datastore":"vm-9011-disk-0","replicate":true,"serial":"","size":10,"speed":[],"ssd":false}],"efi_disk":[],"hook_script_file_id":null,"hostpci":[],"hotplug":null,"id":"9011","initialization":[{"datastore_id":"local-lvm","dns":[],"file_format":"","interface":"ide2","ip_config":[{"ipv4":[{"address":"10.1.90.101/24","gateway":"10.1.90.1"}],"ipv6":[]}],"meta_data_file_id":"","network_data_file_id":"","type":"","upgrade":true,"user_account":[{"keys":["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDV8PkUNKeIftHKf+nrS9CH9pUlOSJ8s27ejEgqH3kAs dorygann@fedora"],"password":"","username":"nidoradmin"}],"user_data_file_id":"","vendor_data_file_id":""}],"ipv4_addresses":[["127.0.0.1"],["10.1.90.101"]],"ipv6_addresses":[["::1"],["fe80::be24:11ff:fe7c:d4ab"]],"keyboard_layout":"en-us","kvm_arguments":null,"mac_addresses":["00:00:00:00:00:00","BC:24:11:7C:D4:AB"],"machine":null,"memory":[{"dedicated":1024,"floating":0,"hugepages":"","keep_hugepages":false,"shared":0}],"migrate":false,"name":"9999aaab","network_device":[{"bridge":"vmbr0","disconnected":false,"enabled":true,"firewall":false,"mac_address":"BC:24:11:7C:D4:AB","model":"virtio","mtu":0,"queues":0,"rate_limit":0,"trunks":"","vlan_id":90}],"network_interface_names":["lo","eth0"],"node_name":"npx-666942cd","numa":[],"on_boot":true,"operating_system":[],"pool_id":"","protection":false,"purge_on_destroy":true,"reboot":false,"reboot_after_update":true,"rng":[],"scsi_hardware":"virtio-scsi-pci","serial_device":[],"smbios":[],"started":true,"startup":[],"stop_on_destroy":false,"tablet_device":true,"tags":null,"template":false,"timeout_clone":1800,"timeout_create":1800,"timeout_migrate":1800,"timeout_move_disk":1800,"timeout_reboot":1800,"timeout_shutdown_vm":1800,"timeout_start_vm":1800,"timeout_stop_vm":300,"tpm_state":[],"usb":[],"vga":[],"virtiofs":[],"vm_id":9011,"watchdog":[]},"sensitive_attributes":[[{"type":"get_attr","value":"initialization"},{"type":"index","value":{"value":0,"type":"number"}},{"type":"get_attr","value":"user_account"},{"type":"index","value":{"value":0,"type":"number"}},{"type":"get_attr","value":"password"}]],"private":"bnVsbA=="},{"index_key":"9999aaac","schema_version":0,"attributes":{"acpi":true,"agent":[{"enabled":true,"timeout":"15m","trim":false,"type":"virtio","wait_for_ip":[]}],"amd_sev":[],"audio_device":[],"bios":"seabios","boot_order":[],"cdrom":[],"clone":[{"datastore_id":"","full":true,"node_name":"","retries":1,"vm_id":100}],"cpu":[{"affinity":"","architecture":"","cores":12,"flags":null,"hotplugged":2,"limit":0,"numa":false,"sockets":1,"type":"qemu64","units":0}],"delete_unreferenced_disks_on_destroy":true,"description":null,"disk":[{"aio":"io_uring","backup":true,"cache":"none","datastore_id":"local-lvm","discard":"ignore","file_format":"raw","file_id":"","import_from":"","interface":"scsi0","iothread":false,"path_in_datastore":"vm-9012-disk-0","replicate":true,"serial":"","size":10,"speed":[],"ssd":false}],"efi_disk":[],"hook_script_file_id":null,"hostpci":[],"hotplug":null,"id":"9012","initialization":[{"datastore_id":"local-lvm","dns":[],"file_format":"","interface":"ide2","ip_config":[{"ipv4":[{"address":"10.1.90.102/24","gateway":"10.1.90.1"}],"ipv6":[]}],"meta_data_file_id":"","network_data_file_id":"","type":"","upgrade":true,"user_account":[{"keys":["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDV8PkUNKeIftHKf+nrS9CH9pUlOSJ8s27ejEgqH3kAs dorygann@fedora"],"password":"","username":"nidoradmin"}],"user_data_file_id":"","vendor_data_file_id":""}],"ipv4_addresses":[["127.0.0.1"],["10.1.90.102"]],"ipv6_addresses":[["::1"],["fe80::be24:11ff:fe45:9627"]],"keyboard_layout":"en-us","kvm_arguments":null,"mac_addresses":["00:00:00:00:00:00","BC:24:11:45:96:27"],"machine":null,"memory":[{"dedicated":1024,"floating":0,"hugepages":"","keep_hugepages":false,"shared":0}],"migrate":false,"name":"9999aaac","network_device":[{"bridge":"vmbr0","disconnected":false,"enabled":true,"firewall":false,"mac_address":"BC:24:11:45:96:27","model":"virtio","mtu":0,"queues":0,"rate_limit":0,"trunks":"","vlan_id":90}],"network_interface_names":["lo","eth0"],"node_name":"npx-666942cd","numa":[],"on_boot":true,"operating_system":[],"pool_id":"","protection":false,"purge_on_destroy":true,"reboot":false,"reboot_after_update":true,"rng":[],"scsi_hardware":"virtio-scsi-pci","serial_device":[],"smbios":[],"started":true,"startup":[],"stop_on_destroy":false,"tablet_device":true,"tags":null,"template":false,"timeout_clone":1800,"timeout_create":1800,"timeout_migrate":1800,"timeout_move_disk":1800,"timeout_reboot":1800,"timeout_shutdown_vm":1800,"timeout_start_vm":1800,"timeout_stop_vm":300,"tpm_state":[],"usb":[],"vga":[],"virtiofs":[],"vm_id":9012,"watchdog":[]},"sensitive_attributes":[[{"type":"get_attr","value":"initialization"},{"type":"index","value":{"value":0,"type":"number"}},{"type":"get_attr","value":"user_account"},{"type":"index","value":{"value":0,"type":"number"}},{"type":"get_attr","value":"password"}]],"private":"bnVsbA=="}]}],"check_results":[{"object_kind":"var","config_addr":"var.vm_count","status":"pass","objects":[{"object_addr":"var.vm_count","status":"pass"}]}]} diff --git a/terraform.tfvars b/terraform.tfvars new file mode 100644 index 0000000..5b8801a --- /dev/null +++ b/terraform.tfvars @@ -0,0 +1,10 @@ +# Copier en `terraform.tfvars` puis remplacer les placeholders +# par les vraies valeurs. Toutes les variables listees ici sont obligatoires + +proxmox_endpoint = "https://npx-666942cd.nia.nidora.lan:8006" +proxmox_api_token = "tofu@pam!opentofu=f59770a7-df52-4744-a7f2-9b44113924f9" +proxmox_insecure = true + +node_name = "npx-666942cd" + +ssh_public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDV8PkUNKeIftHKf+nrS9CH9pUlOSJ8s27ejEgqH3kAs dorygann@fedora" diff --git a/terraform.tfvars.example b/terraform.tfvars.example new file mode 100644 index 0000000..937d399 --- /dev/null +++ b/terraform.tfvars.example @@ -0,0 +1,16 @@ +# Copier en `terraform.tfvars` puis remplacer les placeholders par les vraies valeurs. +# Toutes les variables listees ici sont obligatoires (sans default cote variables.tf). +# +# Note : `vm_count` est aussi obligatoire mais volontairement absente ici pour +# etre promptee a chaque `tofu plan` / `tofu apply`. Decommenter la ligne en bas +# si tu veux la figer. + +proxmox_endpoint = "https://:8006" +proxmox_api_token = "root@pam!sio-routage=00000000-0000-0000-0000-000000000000" +proxmox_insecure = true + +node_name = "" + +ssh_public_key = "ssh-ed25519 AAAA... user@host" + +# vm_count = 3 diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..ba3d92d --- /dev/null +++ b/variables.tf @@ -0,0 +1,99 @@ +# =================== OBLIGATOIRES (sans default) =================== + +variable "proxmox_endpoint" { + description = "URL HTTPS Proxmox" + type = string +} + +variable "proxmox_api_token" { + description = "USER@REALM!TOKENID=SECRET" + type = string + sensitive = true +} + +variable "proxmox_insecure" { + description = "Skip TLS" + type = bool +} + +variable "node_name" { + description = "Nom du node PVE" + type = string +} + +variable "ssh_public_key" { + description = "Cle SSH publique cloudinit" + type = string +} + +variable "vm_count" { + description = "Nombre de VMs a deployer (1 a 90)" + type = number + + validation { + condition = var.vm_count >= 1 && var.vm_count <= 90 + error_message = "vm_count doit etre entre 1 et 90 (limite vm_id 9010-9099)." + } +} + +# =================== OPTIONNELLES (avec default) =================== + +variable "template_id" { + description = "ID Proxmox du template a cloner" + type = number + default = 100 +} + +variable "vm_cpu_sockets" { + description = "Nombre de sockets alloues a la VM" + type = number + default = 1 +} + +variable "vm_cpu_cores" { + description = "Nombre de vCPU alloues a la VM" + type = number + default = 12 +} + +variable "vm_cpu_hotplugged" { + description = "Nombre de vCPUs actifs au boot" + type = number + default = 2 +} + +variable "vm_memory" { + description = "RAM dediee a la VM en MiB" + type = number + default = 1024 +} + +variable "vm_disk_size" { + description = "Taille du disque en GiB" + type = number + default = 10 +} + +variable "bridge" { + description = "Bridge Proxmox" + type = string + default = "vmbr0" +} + +variable "vlan_id" { + description = "VLAN tag applique" + type = number + default = 90 +} + +variable "ci_user" { + description = "Compte unix cree par cloud-init" + type = string + default = "nidoradmin" +} + +variable "gateway" { + description = "Gateway IPv4 du subnet" + type = string + default = "10.1.90.1" +} diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..b234dd2 --- /dev/null +++ b/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.8" + + required_providers { + proxmox = { + source = "bpg/proxmox" + version = "~> 0.78" + } + } +}