├── .markdownlintignore ├── .release-please-manifest.json ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── workflows │ ├── release-please.yml │ └── code-quality.yml └── renovate.json5 ├── example ├── test-api-creds-auth │ ├── .gitignore │ ├── example.tfrc │ ├── versions.tf │ ├── data_object.tf │ ├── main.tf │ └── variables.tf ├── data_source_virtual_environment_metrics_server.tf ├── main.tf ├── resource_virtual_environment_dns.tf ├── data_source_virtual_environment_datastores.tf ├── versions.tf ├── data_source_virtual_environment_pools.tf ├── data_source_virtual_environment_vm.tf ├── data_source_virtual_environment_groups.tf ├── data_source_virtual_environment_role.tf ├── data_source_virtual_environment_container.tf ├── data_source_virtual_environment_dns.tf ├── resource_virtual_environment_cluster_options.tf ├── ssh.tf ├── data_source_virtual_environment_time.tf ├── resource_virtual_environment_role.tf ├── resource_virtual_environment_time.tf ├── data_source_virtual_environment_pool.tf ├── data_source_virtual_environment_group.tf ├── data_source_virtual_environment_roles.tf ├── resource_virtual_environment_pool.tf ├── data_source_virtual_environment_hosts.tf ├── resource_virtual_environment_cluster_firewall_security_group.tf ├── resource_virtual_environment_download_file.tf ├── resource_virtual_environment_group.tf ├── resource_virtual_environment_hosts.tf ├── data_source_virtual_environment_containers.tf ├── data_source_virtual_environment_vms.tf └── data_source_virtual_environment_node.tf ├── example.tfrc ├── terraform-registry-manifest.json ├── examples ├── resources │ ├── proxmox_virtual_environment_metrics_server │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_hagroup │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_acme_account │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_acme_dns_plugin │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_haresource │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_cluster_options │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_sdn_zone_evpn │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_sdn_zone_qinq │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_sdn_zone_vlan │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_sdn_zone_vxlan │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_hardware_mapping_dir │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_sdn_zone_simple │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_apt_repository │ │ ├── resource.tf │ │ └── import.sh │ ├── proxmox_virtual_environment_hardware_mapping_pci │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_hardware_mapping_usb │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_network_linux_vlan │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_network_linux_bridge │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_user_token │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_pool_membership │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_sdn_vnet │ │ └── import.sh │ ├── proxmox_virtual_environment_acl │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_apt_standard_repository │ │ ├── import.sh │ │ └── resource.tf │ ├── proxmox_virtual_environment_sdn_subnet │ │ └── import.sh │ ├── proxmox_virtual_environment_file │ │ └── resource.tf │ └── proxmox_virtual_environment_oci_image │ │ └── resource.tf ├── data-sources │ ├── proxmox_virtual_environment_hagroups │ │ └── data-source.tf │ ├── proxmox_virtual_environment_acme_plugins │ │ └── data-source.tf │ ├── proxmox_virtual_environment_acme_accounts │ │ └── data-source.tf │ ├── proxmox_virtual_environment_acme_plugin │ │ └── data-source.tf │ ├── proxmox_virtual_environment_sdn_vnets │ │ └── data-source.tf │ ├── proxmox_virtual_environment_hardware_mapping_dir │ │ └── data-source.tf │ ├── proxmox_virtual_environment_hardware_mapping_pci │ │ └── data-source.tf │ ├── proxmox_virtual_environment_hardware_mapping_usb │ │ └── data-source.tf │ ├── proxmox_virtual_environment_apt_standard_repository │ │ └── data-source.tf │ ├── proxmox_virtual_environment_apt_repository │ │ └── data-source.tf │ ├── proxmox_virtual_environment_metrics_server │ │ └── data-source.tf │ ├── proxmox_virtual_environment_version │ │ └── data-source.tf │ ├── proxmox_virtual_environment_hagroup │ │ └── data-source.tf │ ├── proxmox_virtual_environment_acme_account │ │ └── data-source.tf │ ├── proxmox_virtual_environment_haresource │ │ └── data-source.tf │ ├── proxmox_virtual_environment_haresources │ │ └── data-source.tf │ ├── proxmox_virtual_environment_sdn_vnet │ │ └── data-source.tf │ ├── proxmox_virtual_environment_hardware_mappings │ │ └── data-source.tf │ ├── proxmox_virtual_environment_sdn_zones │ │ └── data-source.tf │ ├── proxmox_virtual_environment_sdn_zone_simple │ │ └── data-source.tf │ ├── proxmox_virtual_environment_sdn_zone_vlan │ │ └── data-source.tf │ ├── proxmox_virtual_environment_sdn_zone_vxlan │ │ └── data-source.tf │ └── proxmox_virtual_environment_sdn_zone_qinq │ │ └── data-source.tf ├── README.md ├── guides │ ├── cloud-init │ │ ├── native │ │ │ ├── provider.tf │ │ │ └── variables.tf │ │ └── custom │ │ │ ├── variables.tf │ │ │ ├── provider.tf │ │ │ └── cloud-config.tf │ ├── cloud-image │ │ ├── ubuntu-img │ │ │ ├── provider.tf │ │ │ ├── variables.tf │ │ │ └── main.tf │ │ ├── centos-qcow2 │ │ │ ├── variables.tf │ │ │ ├── provider.tf │ │ │ └── main.tf │ │ └── debian-from-storage │ │ │ ├── variables.tf │ │ │ ├── provider.tf │ │ │ └── main.tf │ └── clone-vm │ │ ├── provider.tf │ │ ├── variables.tf │ │ ├── cloud-config.tf │ │ ├── clone.tf │ │ └── template.tf └── provider │ ├── provider.tf │ └── variables.tf ├── .markdownlint.json ├── proxmox ├── cluster │ ├── ha │ │ ├── resources │ │ │ ├── http-client.private.env.json │ │ │ ├── http-client.env.json │ │ │ ├── client.go │ │ │ └── api.http │ │ ├── groups │ │ │ └── client.go │ │ └── client.go │ ├── sdn │ │ ├── applier │ │ │ ├── api.go │ │ │ ├── applier_types.go │ │ │ ├── client.go │ │ │ └── applier.go │ │ ├── sdn_types.go │ │ ├── zones │ │ │ ├── doc.go │ │ │ └── client.go │ │ ├── subnets │ │ │ └── client.go │ │ └── vnets │ │ │ └── client.go │ ├── acme │ │ ├── plugins │ │ │ └── client.go │ │ ├── account │ │ │ └── client.go │ │ └── client.go │ ├── metrics │ │ └── client.go │ ├── mapping │ │ └── client.go │ └── options.go ├── nodes │ ├── storage │ │ ├── upload_types.go │ │ ├── oci_registry_pull_types.go │ │ ├── status.go │ │ ├── storage.go │ │ ├── client.go │ │ ├── status_types.go │ │ └── download_url.go │ ├── firewall │ │ └── client.go │ ├── vms │ │ ├── firewall │ │ │ └── client.go │ │ └── custom_serial_device.go │ ├── containers │ │ └── firewall │ │ │ └── client.go │ ├── hosts_types.go │ ├── apt │ │ └── client.go │ ├── query_url_metadata.go │ ├── config.go │ ├── dns.go │ ├── dns_types.go │ ├── hosts.go │ ├── query_url_metadata_types.go │ └── tasks │ │ └── client.go ├── pools │ └── client.go ├── storage │ ├── client.go │ └── storage_types.go ├── version │ ├── client.go │ ├── version.go │ ├── capabilities.go │ └── version_types.go ├── firewall │ └── client.go ├── ssh │ ├── client_windows.go │ ├── resolver.go │ └── client_notwindows.go ├── access │ └── client.go └── api │ ├── authenticator.go │ ├── errors.go │ ├── client_types.go │ └── token_auth.go ├── qodana.yaml ├── fwprovider ├── config │ ├── doc.go │ ├── datasource.go │ └── resource.go ├── types │ ├── nodes │ │ └── apt │ │ │ └── errors.go │ ├── stringset │ │ └── options.go │ └── ip_addr_value.go ├── validators │ ├── file.go │ ├── sdn.go │ ├── hardware_mapping.go │ ├── i18n.go │ └── strings.go ├── nodes │ └── vm │ │ ├── rng │ │ └── model.go │ │ ├── vga │ │ └── model.go │ │ └── cdrom │ │ └── model.go ├── cluster │ ├── hardwaremapping │ │ └── errors.go │ └── ha │ │ └── validators.go └── test │ └── datasource_node_test.go ├── .vscode ├── extensions.json └── launch.json ├── templates ├── data-sources.md.tmpl ├── data-sources │ └── virtual_environment_vm2.md.tmpl ├── resources.md.tmpl ├── resources │ ├── virtual_environment_pool_membership.md.tmpl │ ├── virtual_environment_download_file.md.tmpl │ └── virtual_environment_vm2.md.tmpl └── guides │ ├── cloud-image.md.tmpl │ └── clone-vm.md.tmpl ├── lychee.toml ├── utils ├── strings.go ├── io.go ├── io_test.go ├── env.go └── sets.go ├── docs ├── data-sources │ ├── virtual_environment_pools.md │ ├── virtual_environment_role.md │ ├── virtual_environment_dns.md │ ├── virtual_environment_groups.md │ ├── virtual_environment_roles.md │ ├── virtual_environment_time.md │ ├── virtual_environment_vm.md │ ├── virtual_environment_acme_accounts.md │ ├── virtual_environment_hosts.md │ ├── virtual_environment_container.md │ ├── virtual_environment_group.md │ ├── virtual_environment_pool.md │ ├── virtual_environment_node.md │ ├── virtual_environment_hagroups.md │ ├── virtual_environment_users.md │ ├── virtual_environment_nodes.md │ ├── virtual_environment_user.md │ ├── virtual_environment_version.md │ ├── virtual_environment_acme_plugin.md │ ├── virtual_environment_sdn_vnets.md │ ├── virtual_environment_sdn_subnet.md │ └── virtual_environment_hardware_mapping_dir.md └── resources │ ├── virtual_environment_time.md │ ├── virtual_environment_role.md │ ├── virtual_environment_pool.md │ ├── virtual_environment_group.md │ └── virtual_environment_dns.md ├── .gitignore ├── .devcontainer ├── Dockerfile └── post-attach.sh ├── proxmoxtf ├── datasource │ ├── pools_test.go │ ├── groups_test.go │ ├── role_test.go │ ├── roles_test.go │ └── dns_test.go └── resource │ ├── validators │ ├── network_test.go │ └── network.go │ ├── role_test.go │ ├── firewall │ └── alias_test.go │ └── dns_test.go └── plan.md /.markdownlintignore: -------------------------------------------------------------------------------- 1 | CHANGELOG.md 2 | -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | ".": "0.89.1" 3 | } 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: bpg 4 | -------------------------------------------------------------------------------- /example/test-api-creds-auth/.gitignore: -------------------------------------------------------------------------------- 1 | cred-tester.config.sh* 2 | outs_cred-tester__expect_*.log 3 | -------------------------------------------------------------------------------- /example.tfrc: -------------------------------------------------------------------------------- 1 | provider_installation { 2 | dev_overrides { 3 | "bpg/proxmox" = "../build" 4 | } 5 | direct {} 6 | } 7 | -------------------------------------------------------------------------------- /terraform-registry-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "metadata": { 4 | "protocol_versions": [ 5 | "6.0" 6 | ] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/test-api-creds-auth/example.tfrc: -------------------------------------------------------------------------------- 1 | provider_installation { 2 | dev_overrides { 3 | "bpg/proxmox" = "../../build" 4 | } 5 | direct {} 6 | } 7 | -------------------------------------------------------------------------------- /example/test-api-creds-auth/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | proxmox = { 4 | source = "bpg/proxmox" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_metrics_server/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | terraform import proxmox_virtual_environment_metrics_server.example example 3 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD007": false, 3 | "MD013": false, 4 | "MD025": false, 5 | "MD028": false, 6 | "MD033": false, 7 | "MD041": false, 8 | "MD059": false 9 | } 10 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_metrics_server.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_metrics_server" "example" { 2 | name = proxmox_virtual_environment_metrics_server.influxdb_server.name 3 | } 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_hagroup/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # HA groups can be imported using their name, e.g.: 3 | terraform import proxmox_virtual_environment_hagroup.example example 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_acme_account/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # ACME accounts can be imported using their name, e.g.: 3 | terraform import proxmox_virtual_environment_acme_account.example example 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_acme_dns_plugin/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # ACME accounts can be imported using their name, e.g.: 3 | terraform import proxmox_virtual_environment_acme_dns_plugin.example test 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_haresource/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # HA resources can be imported using their identifiers, e.g.: 3 | terraform import proxmox_virtual_environment_haresource.example vm:123 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_cluster_options/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Cluster options are global and can be imported using e.g.: 3 | terraform import proxmox_virtual_environment_cluster_options.options cluster 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_evpn/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # EVPN SDN zone can be imported using its unique identifier (zone ID) 3 | terraform import proxmox_virtual_environment_sdn_zone_evpn.example evpn1 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_qinq/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # QinQ SDN zone can be imported using its unique identifier (zone ID) 3 | terraform import proxmox_virtual_environment_sdn_zone_qinq.example qinq1 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_vlan/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # VLAN SDN zone can be imported using its unique identifier (zone ID) 3 | terraform import proxmox_virtual_environment_sdn_zone_vlan.example vlan1 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_vxlan/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # VXLAN SDN zone can be imported using its unique identifier (zone ID) 3 | terraform import proxmox_virtual_environment_sdn_zone_vxlan.example vxlan1 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_hardware_mapping_dir/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # A directory mapping can be imported using their name, e.g.: 3 | terraform import proxmox_virtual_environment_hardware_mapping_dir.example example 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_simple/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Simple SDN zone can be imported using its unique identifier (zone ID) 3 | terraform import proxmox_virtual_environment_sdn_zone_simple.example simple1 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_apt_repository/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_apt_repository" "example" { 2 | enabled = true 3 | file_path = "/etc/apt/sources.list" 4 | index = 0 5 | node = "pve" 6 | } 7 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_hardware_mapping_pci/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # A PCI hardware mapping can be imported using their name, e.g.: 3 | terraform import proxmox_virtual_environment_hardware_mapping_pci.example example 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_hardware_mapping_usb/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # A USB hardware mapping can be imported using their name, e.g.: 3 | terraform import proxmox_virtual_environment_hardware_mapping_usb.example example 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_network_linux_vlan/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | #Interfaces can be imported using the `node_name:iface` format, e.g. 3 | terraform import proxmox_virtual_environment_network_linux_vlan.vlan99 pve:vlan99 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_network_linux_bridge/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | #Interfaces can be imported using the `node_name:iface` format, e.g. 3 | terraform import proxmox_virtual_environment_network_linux_bridge.vmbr99 pve:vmbr99 4 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_user_token/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | #Tokens can be imported using they identifiers in format `user_id!token_name` format, e.g.: 3 | terraform import proxmox_virtual_environment_user_token.token1 user@pve!token1 4 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_hagroups/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_hagroups" "example" {} 2 | 3 | output "data_proxmox_virtual_environment_hagroups" { 4 | value = data.proxmox_virtual_environment_hagroups.example.group_ids 5 | } 6 | -------------------------------------------------------------------------------- /proxmox/cluster/ha/resources/http-client.private.env.json: -------------------------------------------------------------------------------- 1 | { 2 | "utm-8.1-1": { 3 | "api-user": "root@pam", 4 | "api-user-password": "root123" 5 | }, 6 | "adelie": { 7 | "api-user": "root@pam", 8 | "api-user-password": "root123" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /example/main.tf: -------------------------------------------------------------------------------- 1 | provider "proxmox" { 2 | endpoint = var.virtual_environment_endpoint 3 | api_token = var.virtual_environment_api_token 4 | insecure = true 5 | ssh { 6 | agent = true 7 | username = var.virtual_environment_ssh_username 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_acme_plugins/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_acme_plugins" "example" {} 2 | 3 | output "data_proxmox_virtual_environment_acme_plugins" { 4 | value = data.proxmox_virtual_environment_acme_plugins.example.plugins 5 | } 6 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_acme_accounts/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_acme_accounts" "example" {} 2 | 3 | output "data_proxmox_virtual_environment_acme_accounts" { 4 | value = data.proxmox_virtual_environment_acme_accounts.example.accounts 5 | } 6 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_acme_dns_plugin/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_acme_dns_plugin" "example" { 2 | plugin = "test" 3 | api = "aws" 4 | data = { 5 | AWS_ACCESS_KEY_ID = "EXAMPLE" 6 | AWS_SECRET_ACCESS_KEY = "EXAMPLE" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_pool_membership/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Resource pool membership can be imported using its unique identifier, e.g.: {pool_id}/{type}/{member_id} 3 | terraform import proxmox_virtual_environment_pool_membership.example_membership test-pool/vm/102 4 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_acme_plugin/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_acme_plugin" "example" { 2 | plugin = "standalone" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_acme_plugin" { 6 | value = data.proxmox_virtual_environment_acme_plugin.example 7 | } 8 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_vnet/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # SDN vnet can be imported using its unique identifier (vnet ID) 3 | terraform import proxmox_virtual_environment_sdn_vnet.basic_vnet vnet1 4 | terraform import proxmox_virtual_environment_sdn_vnet.isolated_vnet vnet2 5 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_acl/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # ACL can be imported using its unique identifier, e.g.: {path}?{group|user@realm|user@realm!token}?{role} 3 | terraform import proxmox_virtual_environment_acl.operations_automation_monitoring /?monitor@pve?operations-monitoring 4 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_dns.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_dns" "example" { 2 | domain = data.proxmox_virtual_environment_dns.example.domain 3 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 4 | servers = data.proxmox_virtual_environment_dns.example.servers 5 | } 6 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_sdn_vnets/data-source.tf: -------------------------------------------------------------------------------- 1 | # List all SDN VNets 2 | data "proxmox_virtual_environment_sdn_vnets" "all" {} 3 | 4 | output "data_proxmox_virtual_environment_sdn_vnets_all" { 5 | value = { 6 | vnets = data.proxmox_virtual_environment_sdn_vnets.all.vnets 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/test-api-creds-auth/data_object.tf: -------------------------------------------------------------------------------- 1 | 2 | #### two data objects to help show when an auth-failure will fail immediatly with provider or with each TF-request 3 | 4 | 5 | data "proxmox_virtual_environment_nodes" "available_nodes_01" {} 6 | 7 | data "proxmox_virtual_environment_nodes" "available_nodes_02" {} 8 | 9 | -------------------------------------------------------------------------------- /proxmox/cluster/ha/resources/http-client.env.json: -------------------------------------------------------------------------------- 1 | { 2 | "utm-8.1-1": { 3 | "api-path-base": "api2/json", 4 | "host": "https://172.16.1.10", 5 | "port": "8006" 6 | }, 7 | "adelie": { 8 | "api-path-base": "api2/json", 9 | "host": "https://192.168.178.30", 10 | "port": "8006" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_datastores.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_datastores" "example" { 2 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 3 | } 4 | 5 | output "data_proxmox_virtual_environment_datastores_example" { 6 | value = data.proxmox_virtual_environment_datastores.example 7 | } 8 | -------------------------------------------------------------------------------- /example/test-api-creds-auth/main.tf: -------------------------------------------------------------------------------- 1 | provider "proxmox" { 2 | insecure = true 3 | 4 | auth_ticket = var.auth_ticket 5 | csrf_prevention_token = var.csrf_prevention_token 6 | 7 | api_token = var.api_token 8 | 9 | otp = var.otp 10 | 11 | username = var.username 12 | password = var.password 13 | 14 | } 15 | -------------------------------------------------------------------------------- /example/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | local = { 4 | source = "hashicorp/local" 5 | version = "2.6.1" 6 | } 7 | tls = { 8 | source = "hashicorp/tls" 9 | version = "4.1.0" 10 | } 11 | proxmox = { 12 | source = "bpg/proxmox" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_hardware_mapping_dir/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_hardware_mapping_dir" "example" { 2 | name = "example" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_hardware_mapping_dir" { 6 | value = data.proxmox_virtual_environment_hardware_mapping_dir.example 7 | } 8 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_hardware_mapping_pci/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_hardware_mapping_pci" "example" { 2 | name = "example" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_hardware_mapping_pci" { 6 | value = data.proxmox_virtual_environment_hardware_mapping_pci.example 7 | } 8 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_hardware_mapping_usb/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_hardware_mapping_usb" "example" { 2 | name = "example" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_hardware_mapping_usb" { 6 | value = data.proxmox_virtual_environment_hardware_mapping_usb.example 7 | } 8 | -------------------------------------------------------------------------------- /example/test-api-creds-auth/variables.tf: -------------------------------------------------------------------------------- 1 | 2 | variable "auth_ticket" { default = null } 3 | variable "csrf_prevention_token" { default = null } 4 | 5 | variable "api_token" { default = null } 6 | 7 | variable "otp" { default = null } 8 | 9 | variable "username" { default = null } 10 | variable "password" { default = null } 11 | 12 | -------------------------------------------------------------------------------- /qodana.yaml: -------------------------------------------------------------------------------- 1 | version: "1.0" 2 | linter: jetbrains/qodana-go:2025.1 3 | profile: 4 | name: qodana.recommended 5 | exclude: 6 | - name: All 7 | paths: 8 | - CONTRIBUTORS.md 9 | - README.md 10 | - name: GoMixedReceiverTypes 11 | - name: CheckDependencyLicenses 12 | include: 13 | - name: VulnerableLibrariesGlobal 14 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_pools.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_pools" "example" { 2 | depends_on = [proxmox_virtual_environment_pool.example] 3 | } 4 | 5 | output "data_proxmox_virtual_environment_pools_example" { 6 | value = { 7 | pool_ids = data.proxmox_virtual_environment_pools.example.pool_ids 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | `/examples` contain a set of examples that can be used to test the provider as 2 | well as documentation examples. The examples are not meant to be used in 3 | production. 4 | 5 | NOTE: during migration to the TF plugin framework, examples of migrated resources / 6 | data sources will be moving from `/example` to `/examples` folder 7 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_hardware_mapping_dir/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_hardware_mapping_dir" "example" { 2 | comment = "This is a comment" 3 | name = "example" 4 | # The actual map of devices. 5 | map = [ 6 | { 7 | node = "pve" 8 | path = "/mnt/data" 9 | }, 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_haresource/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_haresource" "example" { 2 | depends_on = [ 3 | proxmox_virtual_environment_hagroup.example 4 | ] 5 | resource_id = "vm:123" 6 | state = "started" 7 | group = "example" 8 | comment = "Managed by Terraform" 9 | } 10 | -------------------------------------------------------------------------------- /examples/guides/cloud-init/native/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | proxmox = { 4 | source = "bpg/proxmox" 5 | version = "0.89.1" # x-release-please-version 6 | } 7 | } 8 | } 9 | 10 | provider "proxmox" { 11 | endpoint = var.virtual_environment_endpoint 12 | api_token = var.virtual_environment_token 13 | } 14 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_acme_account/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_acme_account" "example" { 2 | name = "example" 3 | contact = "example@email.com" 4 | directory = "https://acme-staging-v02.api.letsencrypt.org/directory" 5 | tos = "https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf" 6 | } 7 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/ubuntu-img/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | proxmox = { 4 | source = "bpg/proxmox" 5 | version = "0.89.1" # x-release-please-version 6 | } 7 | } 8 | } 9 | 10 | provider "proxmox" { 11 | endpoint = var.virtual_environment_endpoint 12 | api_token = var.virtual_environment_token 13 | } 14 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_apt_standard_repository/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_apt_standard_repository" "example" { 2 | handle = "no-subscription" 3 | node = "pve" 4 | } 5 | 6 | output "proxmox_virtual_environment_apt_standard_repository" { 7 | value = data.proxmox_virtual_environment_apt_standard_repository.example 8 | } 9 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_simple/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_sdn_zone_simple" "example" { 2 | id = "simple1" 3 | nodes = ["pve"] 4 | mtu = 1500 5 | 6 | # Optional attributes 7 | dns = "1.1.1.1" 8 | dns_zone = "example.com" 9 | ipam = "pve" 10 | reverse_dns = "1.1.1.1" 11 | } 12 | -------------------------------------------------------------------------------- /fwprovider/config/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | // Package config provides the global provider's configuration for all resources and datasources. 8 | package config 9 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_apt_repository/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_apt_repository" "example" { 2 | file_path = "/etc/apt/sources.list" 3 | index = 0 4 | node = "pve" 5 | } 6 | 7 | output "proxmox_virtual_environment_apt_repository" { 8 | value = data.proxmox_virtual_environment_apt_repository.example 9 | } 10 | -------------------------------------------------------------------------------- /examples/guides/cloud-init/custom/variables.tf: -------------------------------------------------------------------------------- 1 | variable "virtual_environment_endpoint" { 2 | type = string 3 | description = "The endpoint for the Proxmox Virtual Environment API (example: https://host:port)" 4 | } 5 | 6 | variable "virtual_environment_token" { 7 | type = string 8 | description = "The token for the Proxmox Virtual Environment API" 9 | } 10 | -------------------------------------------------------------------------------- /examples/guides/cloud-init/native/variables.tf: -------------------------------------------------------------------------------- 1 | variable "virtual_environment_endpoint" { 2 | type = string 3 | description = "The endpoint for the Proxmox Virtual Environment API (example: https://host:port)" 4 | } 5 | 6 | variable "virtual_environment_token" { 7 | type = string 8 | description = "The token for the Proxmox Virtual Environment API" 9 | } 10 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/ubuntu-img/variables.tf: -------------------------------------------------------------------------------- 1 | variable "virtual_environment_endpoint" { 2 | type = string 3 | description = "The endpoint for the Proxmox Virtual Environment API (example: https://host:port)" 4 | } 5 | 6 | variable "virtual_environment_token" { 7 | type = string 8 | description = "The token for the Proxmox Virtual Environment API" 9 | } 10 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_apt_repository/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # An APT repository can be imported using a comma-separated list consisting of the name of the Proxmox VE node, 3 | # the absolute source list file path, and the index in the exact same order, e.g.: 4 | terraform import proxmox_virtual_environment_apt_repository.example pve,/etc/apt/sources.list,0 5 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_apt_standard_repository/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # An APT standard repository can be imported using a comma-separated list consisting of the name of the Proxmox VE node, 3 | # and the standard repository handle in the exact same order, e.g.: 4 | terraform import proxmox_virtual_environment_apt_standard_repository.example pve,no-subscription 5 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_hagroup/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_hagroup" "example" { 2 | group = "example" 3 | comment = "This is a comment." 4 | 5 | # Member nodes, with or without priority. 6 | nodes = { 7 | node1 = null 8 | node2 = 2 9 | node3 = 1 10 | } 11 | 12 | restricted = true 13 | no_failback = false 14 | } 15 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/applier/api.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package applier 8 | 9 | import "context" 10 | 11 | type API interface { 12 | ApplyConfig(ctx context.Context) error 13 | } 14 | -------------------------------------------------------------------------------- /examples/provider/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | proxmox = { 4 | source = "bpg/proxmox" 5 | } 6 | } 7 | } 8 | 9 | provider "proxmox" { 10 | endpoint = var.virtual_environment_endpoint 11 | username = var.virtual_environment_username 12 | password = var.virtual_environment_password 13 | insecure = true 14 | ssh { 15 | agent = true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/centos-qcow2/variables.tf: -------------------------------------------------------------------------------- 1 | variable "virtual_environment_endpoint" { 2 | type = string 3 | description = "The endpoint for the Proxmox Virtual Environment API (example: https://host:port)" 4 | } 5 | 6 | variable "virtual_environment_token" { 7 | type = string 8 | description = "The token for the Proxmox Virtual Environment API" 9 | sensitive = true 10 | } 11 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/debian-from-storage/variables.tf: -------------------------------------------------------------------------------- 1 | variable "virtual_environment_endpoint" { 2 | type = string 3 | description = "The endpoint for the Proxmox Virtual Environment API (example: https://host:port)" 4 | } 5 | 6 | variable "virtual_environment_token" { 7 | type = string 8 | description = "The token for the Proxmox Virtual Environment API" 9 | sensitive = true 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "britesnow.vscode-toggle-quotes", 4 | "davidanson.vscode-markdownlint", 5 | "EditorConfig.editorconfig", 6 | "golang.go", 7 | "hashicorp.terraform", 8 | "joshbolduc.commitlint", 9 | "PKief.material-icon-theme", 10 | "psioniq.psi-header", 11 | "ms-azuretools.vscode-docker" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_vm.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_vm" "example" { 2 | depends_on = [proxmox_virtual_environment_vm.example] 3 | vm_id = proxmox_virtual_environment_vm.example.vm_id 4 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 5 | } 6 | 7 | output "proxmox_virtual_environment_vm_example" { 8 | value = data.proxmox_virtual_environment_vm.example 9 | } 10 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/centos-qcow2/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | proxmox = { 4 | source = "bpg/proxmox" 5 | version = "0.89.1" # x-release-please-version 6 | } 7 | } 8 | } 9 | 10 | provider "proxmox" { 11 | endpoint = var.virtual_environment_endpoint 12 | api_token = var.virtual_environment_token 13 | # SSH configuration is not required for this example 14 | } 15 | -------------------------------------------------------------------------------- /examples/guides/clone-vm/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | proxmox = { 4 | source = "bpg/proxmox" 5 | version = "0.89.1" # x-release-please-version 6 | } 7 | } 8 | } 9 | 10 | provider "proxmox" { 11 | endpoint = var.virtual_environment_endpoint 12 | api_token = var.virtual_environment_token 13 | ssh { 14 | agent = true 15 | username = "terraform" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_groups.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_groups" "example" { 2 | depends_on = [proxmox_virtual_environment_group.example] 3 | } 4 | 5 | output "data_proxmox_virtual_environment_groups_example" { 6 | value = tomap({ 7 | "comments" = data.proxmox_virtual_environment_groups.example.comments 8 | "group_ids" = data.proxmox_virtual_environment_groups.example.group_ids 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_metrics_server/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_metrics_server" "example" { 2 | name = "example_influxdb" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_metrics_server" { 6 | value = { 7 | server = data.proxmox_virtual_environment_metrics_server.example.server 8 | port = data.proxmox_virtual_environment_metrics_server.example.port 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/guides/cloud-init/custom/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | proxmox = { 4 | source = "bpg/proxmox" 5 | version = "0.89.1" # x-release-please-version 6 | } 7 | } 8 | } 9 | 10 | provider "proxmox" { 11 | endpoint = var.virtual_environment_endpoint 12 | api_token = var.virtual_environment_token 13 | ssh { 14 | agent = true 15 | username = "terraform" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_vlan/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_sdn_zone_vlan" "example" { 2 | id = "vlan1" 3 | # nodes = ["pve"] # Optional: omit to apply to all nodes in cluster 4 | bridge = "vmbr0" 5 | mtu = 1500 6 | 7 | # Optional attributes 8 | dns = "1.1.1.1" 9 | dns_zone = "example.com" 10 | ipam = "pve" 11 | reverse_dns = "1.1.1.1" 12 | } 13 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/debian-from-storage/provider.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | proxmox = { 4 | source = "bpg/proxmox" 5 | version = "0.89.1" # x-release-please-version 6 | } 7 | } 8 | } 9 | 10 | provider "proxmox" { 11 | endpoint = var.virtual_environment_endpoint 12 | api_token = var.virtual_environment_token 13 | ssh { 14 | agent = true 15 | username = "terraform" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_subnet/import.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # SDN subnet can be imported using its unique identifier in the format: / 3 | # The is the canonical ID from Proxmox, e.g., "zone1-192.168.1.0-24" 4 | terraform import proxmox_virtual_environment_sdn_subnet.basic_subnet vnet1/zone1-192.168.1.0-24 5 | terraform import proxmox_virtual_environment_sdn_subnet.dhcp_subnet vnet2/zone2-192.168.2.0-24 6 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_role.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_role" "example" { 2 | role_id = proxmox_virtual_environment_role.example.id 3 | } 4 | 5 | output "data_proxmox_virtual_environment_role_example_privileges" { 6 | value = data.proxmox_virtual_environment_role.example.privileges 7 | } 8 | 9 | output "data_proxmox_virtual_environment_role_example_role_id" { 10 | value = data.proxmox_virtual_environment_role.example.id 11 | } 12 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_container.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_container" "example" { 2 | depends_on = [proxmox_virtual_environment_container.example] 3 | vm_id = proxmox_virtual_environment_container.example.vm_id 4 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 5 | } 6 | 7 | output "proxmox_virtual_environment_container_example" { 8 | value = data.proxmox_virtual_environment_container.example 9 | } 10 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_dns.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_dns" "example" { 2 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 3 | } 4 | 5 | output "data_proxmox_virtual_environment_dns_example_domain" { 6 | value = data.proxmox_virtual_environment_dns.example.domain 7 | } 8 | 9 | output "data_proxmox_virtual_environment_dns_example_servers" { 10 | value = data.proxmox_virtual_environment_dns.example.servers 11 | } 12 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_cluster_options.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_cluster_options" "options" { 2 | language = "en" 3 | keyboard = "pl" 4 | email_from = "ged@gont.earthsea" 5 | bandwidth_limit_migration = 555555 6 | bandwidth_limit_default = 666666 7 | max_workers = 5 8 | migration_cidr = "10.0.0.0/8" 9 | migration_type = "secure" 10 | } 11 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_version/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_version" "example" {} 2 | 3 | output "data_proxmox_virtual_environment_version" { 4 | value = { 5 | release = data.proxmox_virtual_environment_version.example.release 6 | repository_id = data.proxmox_virtual_environment_version.example.repository_id 7 | version = data.proxmox_virtual_environment_version.example.version 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_vxlan/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_sdn_zone_vxlan" "example" { 2 | id = "vxlan1" 3 | # nodes = ["pve"] # Optional: omit to apply to all nodes in cluster 4 | peers = ["10.0.0.1", "10.0.0.2", "10.0.0.3"] 5 | mtu = 1450 6 | 7 | # Optional attributes 8 | dns = "1.1.1.1" 9 | dns_zone = "example.com" 10 | ipam = "pve" 11 | reverse_dns = "1.1.1.1" 12 | } 13 | -------------------------------------------------------------------------------- /templates/data-sources.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: {{.Name}} 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }} 8 | --- 9 | 10 | # {{.Type}}: {{.Name}} 11 | 12 | {{ .Description | trimspace }} 13 | 14 | {{ if .HasExample -}} 15 | ## Example Usage 16 | 17 | {{ codefile "terraform" .ExampleFile }} 18 | {{- end }} 19 | 20 | {{ .SchemaMarkdown | trimspace }} 21 | -------------------------------------------------------------------------------- /proxmox/nodes/storage/upload_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | // DatastoreUploadResponseBody contains the body from a datastore upload response. 10 | type DatastoreUploadResponseBody struct { 11 | UploadID *string `json:"data,omitempty"` 12 | } 13 | -------------------------------------------------------------------------------- /proxmox/pools/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package pools 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 11 | ) 12 | 13 | // Client is an interface for accessing the Proxmox pools API. 14 | type Client struct { 15 | api.Client 16 | } 17 | -------------------------------------------------------------------------------- /fwprovider/config/datasource.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package config 8 | 9 | import "github.com/bpg/terraform-provider-proxmox/proxmox" 10 | 11 | // DataSource is the global configuration for all datasources. 12 | type DataSource struct { 13 | Client proxmox.Client 14 | } 15 | -------------------------------------------------------------------------------- /proxmox/storage/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 11 | ) 12 | 13 | // Client is an interface for accessing the Proxmox storage API. 14 | type Client struct { 15 | api.Client 16 | } 17 | -------------------------------------------------------------------------------- /proxmox/version/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package version 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 11 | ) 12 | 13 | // Client is an interface for accessing the Proxmox version API. 14 | type Client struct { 15 | api.Client 16 | } 17 | -------------------------------------------------------------------------------- /example/ssh.tf: -------------------------------------------------------------------------------- 1 | resource "local_sensitive_file" "example_ssh_private_key" { 2 | filename = "${path.module}/autogenerated/id_rsa" 3 | content = tls_private_key.example.private_key_pem 4 | } 5 | 6 | resource "local_sensitive_file" "example_ssh_public_key" { 7 | filename = "${path.module}/autogenerated/id_rsa.pub" 8 | content = tls_private_key.example.public_key_openssh 9 | } 10 | 11 | resource "tls_private_key" "example" { 12 | algorithm = "RSA" 13 | rsa_bits = 2048 14 | } 15 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_time.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_time" "example" { 2 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 3 | } 4 | 5 | output "data_proxmox_virtual_environment_time" { 6 | value = { 7 | local_time = data.proxmox_virtual_environment_time.example.local_time 8 | time_zone = data.proxmox_virtual_environment_time.example.time_zone 9 | utc_time = data.proxmox_virtual_environment_time.example.utc_time 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /proxmox/nodes/firewall/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package firewall 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/firewall" 11 | ) 12 | 13 | // Client is an interface for accessing the Proxmox node firewall API. 14 | type Client struct { 15 | firewall.Client 16 | } 17 | -------------------------------------------------------------------------------- /proxmox/nodes/vms/firewall/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package firewall 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/firewall" 11 | ) 12 | 13 | // Client is an interface for accessing the Proxmox VM firewall API. 14 | type Client struct { 15 | firewall.Client 16 | } 17 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_role.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_role" "example" { 2 | privileges = [ 3 | "VM.GuestAgent.Audit", 4 | ] 5 | role_id = "terraform-provider-proxmox-example" 6 | } 7 | 8 | output "resource_proxmox_virtual_environment_role_example_privileges" { 9 | value = proxmox_virtual_environment_role.example.privileges 10 | } 11 | 12 | output "resource_proxmox_virtual_environment_role_example_role_id" { 13 | value = proxmox_virtual_environment_role.example.role_id 14 | } 15 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_network_linux_vlan/resource.tf: -------------------------------------------------------------------------------- 1 | # using VLAN tag 2 | resource "proxmox_virtual_environment_network_linux_vlan" "vlan99" { 3 | node_name = "pve" 4 | name = "eno0.99" 5 | 6 | comment = "VLAN 99" 7 | } 8 | 9 | # using custom network interface name 10 | resource "proxmox_virtual_environment_network_linux_vlan" "vlan98" { 11 | node_name = "pve" 12 | name = "vlan_lab" 13 | 14 | interface = "eno0" 15 | vlan = 98 16 | comment = "VLAN 98" 17 | } 18 | -------------------------------------------------------------------------------- /templates/data-sources/virtual_environment_vm2.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: {{.Name}} 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }} 8 | --- 9 | 10 | # {{.Type}}: {{.Name}} 11 | 12 | !> **DO NOT USE** 13 | {{ .Description | trimspace }} 14 | 15 | {{ if .HasExample -}} 16 | ## Example Usage 17 | 18 | {{ codefile "terraform" .ExampleFile }} 19 | {{- end }} 20 | 21 | {{ .SchemaMarkdown | trimspace }} 22 | -------------------------------------------------------------------------------- /proxmox/nodes/containers/firewall/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package firewall 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/firewall" 11 | ) 12 | 13 | // Client is an interface for accessing the Proxmox container firewall API. 14 | type Client struct { 15 | firewall.Client 16 | } 17 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_qinq/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_sdn_zone_qinq" "example" { 2 | id = "qinq1" 3 | # nodes = ["pve"] # Optional: omit to apply to all nodes in cluster 4 | bridge = "vmbr0" 5 | service_vlan = 100 6 | service_vlan_protocol = "802.1ad" 7 | mtu = 1496 8 | 9 | # Optional attributes 10 | dns = "1.1.1.1" 11 | dns_zone = "example.com" 12 | ipam = "pve" 13 | reverse_dns = "1.1.1.1" 14 | } 15 | -------------------------------------------------------------------------------- /lychee.toml: -------------------------------------------------------------------------------- 1 | # Lychee configuration file 2 | # Exclude specific files from link checking 3 | exclude_path = [ 4 | "CONTRIBUTORS.md", 5 | "CHANGELOG.md", 6 | "cache", 7 | ".terraform" 8 | ] 9 | 10 | # Exclude URL patterns (regex) 11 | exclude = [ 12 | "https://.*:8006/" # Exclude Proxmox server URLs 13 | ] 14 | 15 | # Base directory for relative paths 16 | base = "." 17 | 18 | # Enable verbose output 19 | verbose = "warn" 20 | 21 | # Disable progress bar (better for CI) 22 | no_progress = true 23 | 24 | accept = [429, 200] 25 | -------------------------------------------------------------------------------- /examples/provider/variables.tf: -------------------------------------------------------------------------------- 1 | variable "virtual_environment_endpoint" { 2 | type = string 3 | description = "The endpoint for the Proxmox Virtual Environment API (example: https://host:port)" 4 | } 5 | 6 | variable "virtual_environment_password" { 7 | type = string 8 | description = "The password for the Proxmox Virtual Environment API" 9 | } 10 | 11 | variable "virtual_environment_username" { 12 | type = string 13 | description = "The username and realm for the Proxmox Virtual Environment API (example: root@pam)" 14 | } 15 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_hardware_mapping_usb/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_hardware_mapping_usb" "example" { 2 | comment = "This is a comment" 3 | name = "example" 4 | # The actual map of devices. 5 | map = [ 6 | { 7 | comment = "This is a device specific comment" 8 | id = "8087:0a2b" 9 | node = "pve" 10 | # This attribute is optional, but can be used to map the device based on its port instead of only the device ID. 11 | path = "1-8.2" 12 | }, 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_time.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_time" "example" { 2 | node_name = data.proxmox_virtual_environment_time.example.node_name 3 | time_zone = data.proxmox_virtual_environment_time.example.time_zone 4 | } 5 | 6 | output "resource_proxmox_virtual_environment_time" { 7 | value = { 8 | local_time = proxmox_virtual_environment_time.example.local_time 9 | time_zone = proxmox_virtual_environment_time.example.time_zone 10 | utc_time = proxmox_virtual_environment_time.example.utc_time 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_hagroup/data-source.tf: -------------------------------------------------------------------------------- 1 | // This will fetch the set of HA group identifiers... 2 | data "proxmox_virtual_environment_hagroups" "all" {} 3 | 4 | // ...which we will go through in order to fetch the whole data on each group. 5 | data "proxmox_virtual_environment_hagroup" "example" { 6 | for_each = data.proxmox_virtual_environment_hagroups.all.group_ids 7 | group = each.value 8 | } 9 | 10 | output "proxmox_virtual_environment_hagroups_full" { 11 | value = data.proxmox_virtual_environment_hagroup.example 12 | } 13 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_apt_standard_repository/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_apt_standard_repository" "example" { 2 | handle = "no-subscription" 3 | node = "pve" 4 | } 5 | 6 | resource "proxmox_virtual_environment_apt_repository" "example" { 7 | enabled = true 8 | file_path = proxmox_virtual_environment_apt_standard_repository.example.file_path 9 | index = proxmox_virtual_environment_apt_standard_repository.example.index 10 | node = proxmox_virtual_environment_apt_standard_repository.example.node 11 | } 12 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_acme_account/data-source.tf: -------------------------------------------------------------------------------- 1 | // This will fetch all ACME accounts... 2 | data "proxmox_virtual_environment_acme_accounts" "all" {} 3 | 4 | // ...which we will go through in order to fetch the whole data on each account. 5 | data "proxmox_virtual_environment_acme_account" "example" { 6 | for_each = data.proxmox_virtual_environment_acme_accounts.all.accounts 7 | name = each.value 8 | } 9 | 10 | output "data_proxmox_virtual_environment_acme_account" { 11 | value = data.proxmox_virtual_environment_acme_account.example 12 | } 13 | -------------------------------------------------------------------------------- /utils/strings.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package utils 8 | 9 | // ConvertToStringSlice helps convert interface slice to string slice. 10 | func ConvertToStringSlice(interfaceSlice []any) []string { 11 | resultSlice := make([]string, len(interfaceSlice)) 12 | 13 | for i, val := range interfaceSlice { 14 | resultSlice[i] = val.(string) 15 | } 16 | 17 | return resultSlice 18 | } 19 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/sdn_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package sdn 8 | 9 | import "github.com/bpg/terraform-provider-proxmox/proxmox/types" 10 | 11 | // QueryParams represents optionally query parameters for all SDN API calls. 12 | type QueryParams struct { 13 | Pending *types.CustomBool `url:"pending,omitempty,int"` 14 | Running *types.CustomBool `url:"running,omitempty,int"` 15 | } 16 | -------------------------------------------------------------------------------- /fwprovider/config/resource.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package config 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox" 11 | "github.com/bpg/terraform-provider-proxmox/proxmox/cluster" 12 | ) 13 | 14 | // Resource is the global configuration for all resources. 15 | type Resource struct { 16 | Client proxmox.Client 17 | 18 | IDGenerator cluster.IDGenerator 19 | } 20 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_pool.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_pool" "example" { 2 | pool_id = proxmox_virtual_environment_pool.example.id 3 | } 4 | 5 | output "data_proxmox_virtual_environment_pool_example_comment" { 6 | value = data.proxmox_virtual_environment_pool.example.comment 7 | } 8 | 9 | output "data_proxmox_virtual_environment_pool_example_members" { 10 | value = data.proxmox_virtual_environment_pool.example.members 11 | } 12 | 13 | output "data_proxmox_virtual_environment_pool_example_pool_id" { 14 | value = data.proxmox_virtual_environment_pool.example.id 15 | } 16 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_haresource/data-source.tf: -------------------------------------------------------------------------------- 1 | // This will fetch the set of all HA resource identifiers... 2 | data "proxmox_virtual_environment_haresources" "all" {} 3 | 4 | // ...which we will go through in order to fetch the whole record for each resource. 5 | data "proxmox_virtual_environment_haresource" "example" { 6 | for_each = data.proxmox_virtual_environment_haresources.all.resource_ids 7 | resource_id = each.value 8 | } 9 | 10 | output "proxmox_virtual_environment_haresources_full" { 11 | value = data.proxmox_virtual_environment_haresource.example 12 | } 13 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_pools.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_pools 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_pools 9 | 10 | Retrieves the identifiers for all the available resource pools. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_pools" "available_pools" {} 16 | ``` 17 | 18 | ## Argument Reference 19 | 20 | There are no arguments available for this data source. 21 | 22 | ## Attribute Reference 23 | 24 | - `pool_ids` - The pool identifiers. 25 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_group.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_group" "example" { 2 | group_id = proxmox_virtual_environment_group.example.id 3 | } 4 | 5 | output "data_proxmox_virtual_environment_group_example_acl" { 6 | value = data.proxmox_virtual_environment_group.example.acl 7 | } 8 | 9 | output "data_proxmox_virtual_environment_group_example_comment" { 10 | value = data.proxmox_virtual_environment_group.example.comment 11 | } 12 | 13 | output "data_proxmox_virtual_environment_group_example_members" { 14 | value = data.proxmox_virtual_environment_group.example.members 15 | } 16 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_role.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_role 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_role 9 | 10 | Retrieves information about a specific role. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_role" "operations_role" { 16 | role_id = "operations" 17 | } 18 | ``` 19 | 20 | ## Argument Reference 21 | 22 | - `role_id` - (Required) The role identifier. 23 | 24 | ## Attribute Reference 25 | 26 | - `privileges` - The role privileges 27 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_roles.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_roles" "example" { 2 | depends_on = [proxmox_virtual_environment_role.example] 3 | } 4 | 5 | output "data_proxmox_virtual_environment_roles_example_privileges" { 6 | value = data.proxmox_virtual_environment_roles.example.privileges 7 | } 8 | 9 | output "data_proxmox_virtual_environment_roles_example_role_ids" { 10 | value = data.proxmox_virtual_environment_roles.example.role_ids 11 | } 12 | 13 | output "data_proxmox_virtual_environment_roles_example_special" { 14 | value = data.proxmox_virtual_environment_roles.example.special 15 | } 16 | -------------------------------------------------------------------------------- /proxmox/firewall/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package firewall 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 11 | ) 12 | 13 | // API is an interface for the Proxmox firewall API. 14 | type API interface { 15 | Alias 16 | IPSet 17 | Rule 18 | Options 19 | } 20 | 21 | // Client is an interface for accessing the Proxmox firewall API. 22 | type Client struct { 23 | api.Client 24 | } 25 | -------------------------------------------------------------------------------- /proxmox/ssh/client_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package ssh 4 | 5 | import ( 6 | "context" 7 | "fmt" 8 | "net" 9 | 10 | "github.com/Microsoft/go-winio" 11 | ) 12 | 13 | // dialSocket dials a Windows named pipe. If address is empty, it dials the default ssh-agent pipe. 14 | func dialSocket(ctx context.Context, address string) (net.Conn, error) { 15 | if address == "" { 16 | address = `\\.\pipe\openssh-ssh-agent` 17 | } 18 | 19 | conn, err := winio.DialPipeContext(ctx, address) 20 | if err != nil { 21 | return nil, fmt.Errorf("error dialing named pipe: %w", err) 22 | } 23 | 24 | return conn, nil 25 | } 26 | -------------------------------------------------------------------------------- /templates/resources.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: {{.Name}} 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | description: |- 7 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }} 8 | --- 9 | 10 | # {{.Type}}: {{.Name}} 11 | 12 | {{ .Description | trimspace }} 13 | 14 | {{ if .HasExample -}} 15 | ## Example Usage 16 | 17 | {{ codefile "terraform" .ExampleFile }} 18 | {{- end }} 19 | 20 | {{ .SchemaMarkdown | trimspace }} 21 | {{- if .HasImport }} 22 | 23 | ## Import 24 | 25 | Import is supported using the following syntax: 26 | 27 | {{ codefile "shell" .ImportFile }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_pool.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_pool" "example" { 2 | comment = "Managed by Terraform" 3 | pool_id = "terraform-provider-proxmox-example" 4 | } 5 | 6 | output "resource_proxmox_virtual_environment_pool_example_comment" { 7 | value = proxmox_virtual_environment_pool.example.comment 8 | } 9 | 10 | output "resource_proxmox_virtual_environment_pool_example_members" { 11 | value = proxmox_virtual_environment_pool.example.members 12 | } 13 | 14 | output "resource_proxmox_virtual_environment_pool_example_pool_id" { 15 | value = proxmox_virtual_environment_pool.example.id 16 | } 17 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/applier/applier_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package applier 8 | 9 | // ApplyResponseBody represents the response of PUT /cluster/sdn. 10 | // PVE typically returns a UPID string in `data` for async tasks. 11 | // We keep it here even if ApplyConfig currently ignores it, so the 12 | // API can easily be extended later to surface it. 13 | type ApplyResponseBody struct { 14 | Data *string `json:"data"` 15 | } 16 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_dns.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_dns 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_dns 9 | 10 | Retrieves the DNS configuration for a specific node. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_dns" "first_node" { 16 | node_name = "first-node" 17 | } 18 | ``` 19 | 20 | ## Argument Reference 21 | 22 | - `node_name` - (Required) A node name. 23 | 24 | ## Attribute Reference 25 | 26 | - `domain` - The DNS search domain. 27 | - `servers` - The DNS servers. 28 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_groups.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_groups 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_groups 9 | 10 | Retrieves basic information about all available user groups. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_groups" "available_groups" {} 16 | ``` 17 | 18 | ## Argument Reference 19 | 20 | There are no arguments available for this data source. 21 | 22 | ## Attribute Reference 23 | 24 | - `comments` - The group comments. 25 | - `group_ids` - The group identifiers. 26 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_haresources/data-source.tf: -------------------------------------------------------------------------------- 1 | // This will fetch the set of all HA resource identifiers. 2 | data "proxmox_virtual_environment_haresources" "example_all" {} 3 | 4 | // This will fetch the set of HA resource identifiers that correspond to virtual machines. 5 | data "proxmox_virtual_environment_haresources" "example_vm" { 6 | type = "vm" 7 | } 8 | 9 | output "data_proxmox_virtual_environment_haresources" { 10 | value = { 11 | all = data.proxmox_virtual_environment_haresources.example_all.resource_ids 12 | vms = data.proxmox_virtual_environment_haresources.example_vm.resource_ids 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_user_token/resource.tf: -------------------------------------------------------------------------------- 1 | # if creating a user token, the user must be created first 2 | resource "proxmox_virtual_environment_user" "user" { 3 | comment = "Managed by Terraform" 4 | email = "user@pve" 5 | enabled = true 6 | expiration_date = "2034-01-01T22:00:00Z" 7 | user_id = "user@pve" 8 | } 9 | 10 | resource "proxmox_virtual_environment_user_token" "user_token" { 11 | comment = "Managed by Terraform" 12 | expiration_date = "2033-01-01T22:00:00Z" 13 | token_name = "tk1" 14 | user_id = proxmox_virtual_environment_user.user.user_id 15 | } 16 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/zones/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | // Package zones provides types and structures for managing Proxmox VE Software Defined Network (SDN) zones. 8 | // SDN zones are logical network segments that can be configured with different network types including 9 | // VLAN, QinQ, VXLAN, and EVPN. This package contains the data structures used for creating, updating, 10 | // and managing SDN zones through the Proxmox API. 11 | package zones 12 | -------------------------------------------------------------------------------- /fwprovider/types/nodes/apt/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | This Source Code Form is subject to the terms of the Mozilla Public 3 | License, v. 2.0. If a copy of the MPL was not distributed with this 4 | file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package apt 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/hashicorp/terraform-plugin-framework/function" 13 | ) 14 | 15 | //nolint:gochecknoglobals 16 | var ( 17 | // ErrValueConversion indicates an error while converting a value for a Proxmox VE API APT entity. 18 | ErrValueConversion = func(format string, attrs ...any) error { 19 | return function.NewFuncError(fmt.Sprintf(format, attrs...)) 20 | } 21 | ) 22 | -------------------------------------------------------------------------------- /proxmox/ssh/resolver.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package ssh 8 | 9 | import ( 10 | "context" 11 | ) 12 | 13 | // ProxmoxNode represents node address and port for SSH connection. 14 | type ProxmoxNode struct { 15 | Address string 16 | Port int32 17 | } 18 | 19 | // NodeResolver is an interface for resolving node names to IP addresses to use for SSH connection. 20 | type NodeResolver interface { 21 | Resolve(ctx context.Context, nodeName string) (ProxmoxNode, error) 22 | } 23 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_roles.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_roles 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_roles 9 | 10 | Retrieves information about all the available roles. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_roles" "available_roles" {} 16 | ``` 17 | 18 | ## Argument Reference 19 | 20 | There are no arguments available for this data source. 21 | 22 | ## Attribute Reference 23 | 24 | - `privileges` - The role privileges. 25 | - `role_ids` - The role identifiers. 26 | - `special` - Whether the role is special (built-in). 27 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_pool_membership/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_vm" "test_vm1" { 2 | vm_id = 1234 3 | node_name = "pve" 4 | started = false 5 | } 6 | 7 | resource "proxmox_virtual_environment_pool" "test_pool" { 8 | pool_id = "test-pool" 9 | } 10 | 11 | resource "proxmox_virtual_environment_pool_membership" "vm_membership" { 12 | pool_id = proxmox_virtual_environment_pool.test_pool.id 13 | vm_id = proxmox_virtual_environment_vm.test_vm1.id 14 | } 15 | 16 | resource "proxmox_virtual_environment_pool_membership" "storage_membership" { 17 | pool_id = proxmox_virtual_environment_pool.test_pool.id 18 | storage_id = "local-lvm" 19 | } -------------------------------------------------------------------------------- /proxmox/access/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package access 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | ) 14 | 15 | // Client is an interface for performing requests against the Proxmox 'access' API. 16 | type Client struct { 17 | api.Client 18 | } 19 | 20 | // ExpandPath expands a path relative to the client's base path. 21 | func (c *Client) ExpandPath(path string) string { 22 | return fmt.Sprintf("access/%s", path) 23 | } 24 | -------------------------------------------------------------------------------- /proxmox/ssh/client_notwindows.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package ssh 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net" 10 | ) 11 | 12 | // dialSocket dials a Unix domain socket. 13 | func dialSocket(ctx context.Context, address string) (net.Conn, error) { 14 | if address == "" { 15 | return nil, errors.New("failed connecting to SSH agent socket: the socket file is not defined, " + 16 | "authentication will fall back to password") 17 | } 18 | 19 | dialer := &net.Dialer{} 20 | 21 | conn, err := dialer.DialContext(ctx, "unix", address) 22 | if err != nil { 23 | return nil, fmt.Errorf("error dialing unix socket: %w", err) 24 | } 25 | 26 | return conn, nil 27 | } 28 | -------------------------------------------------------------------------------- /utils/io.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package utils 8 | 9 | import ( 10 | "context" 11 | "io" 12 | 13 | "github.com/hashicorp/terraform-plugin-log/tflog" 14 | ) 15 | 16 | // CloseOrLogError closes the given io.Closer and logs any error. 17 | func CloseOrLogError(ctx context.Context) func(io.Closer) { 18 | return func(c io.Closer) { 19 | if err := c.Close(); err != nil { 20 | tflog.Error(ctx, "Failed to close", map[string]any{ 21 | "error": err, 22 | }) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_time.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_time 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_time 9 | 10 | Retrieves the current time for a specific node. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_time" "first_node_time" { 16 | node_name = "first-node" 17 | } 18 | ``` 19 | 20 | ## Argument Reference 21 | 22 | - `node_name` - (Required) A node name. 23 | 24 | ## Attribute Reference 25 | 26 | - `local_time` - The node's local time. 27 | - `time_zone` - The node's time zone. 28 | - `utc_time` - The node's local time formatted as UTC. 29 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_file/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_file" "latest_debian_12_bookworm_qcow2" { 2 | content_type = "import" 3 | datastore_id = "local" 4 | node_name = "pve" 5 | 6 | source_file { 7 | path = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2" 8 | } 9 | } 10 | 11 | resource "proxmox_virtual_environment_file" "release_20231228_debian_12_bookworm_qcow2" { 12 | content_type = "import" 13 | datastore_id = "local" 14 | node_name = "pve" 15 | 16 | source_file { 17 | path = "https://cloud.debian.org/images/cloud/bookworm/20231228-1609/debian-12-generic-amd64-20231228-1609.qcow2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /proxmox/cluster/acme/plugins/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package plugins 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | ) 14 | 15 | // Client is an interface for accessing the Proxmox ACME plugins API. 16 | type Client struct { 17 | api.Client 18 | } 19 | 20 | // ExpandPath expands a relative path to the Proxmox ACME plugins API path. 21 | func (c *Client) ExpandPath(path string) string { 22 | return fmt.Sprintf("cluster/acme/plugins/%s", path) 23 | } 24 | -------------------------------------------------------------------------------- /proxmox/nodes/vms/custom_serial_device.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package vms 8 | 9 | import ( 10 | "fmt" 11 | "net/url" 12 | ) 13 | 14 | // CustomSerialDevices handles QEMU serial device parameters. 15 | type CustomSerialDevices []string 16 | 17 | // EncodeValues converts a CustomSerialDevices array to multiple URL values. 18 | func (r CustomSerialDevices) EncodeValues(key string, v *url.Values) error { 19 | for i, d := range r { 20 | v.Add(fmt.Sprintf("%s%d", key, i), d) 21 | } 22 | 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_sdn_vnet/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_sdn_vnet" "example" { 2 | id = "vnet1" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_sdn_vnet" { 6 | value = { 7 | id = data.proxmox_virtual_environment_sdn_vnet.example.id 8 | zone = data.proxmox_virtual_environment_sdn_vnet.example.zone 9 | alias = data.proxmox_virtual_environment_sdn_vnet.example.alias 10 | isolate_ports = data.proxmox_virtual_environment_sdn_vnet.example.isolate_ports 11 | tag = data.proxmox_virtual_environment_sdn_vnet.example.tag 12 | vlan_aware = data.proxmox_virtual_environment_sdn_vnet.example.vlan_aware 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/guides/clone-vm/variables.tf: -------------------------------------------------------------------------------- 1 | variable "virtual_environment_endpoint" { 2 | type = string 3 | description = "The endpoint for the Proxmox Virtual Environment API (example: https://host:port)" 4 | } 5 | 6 | variable "virtual_environment_token" { 7 | type = string 8 | description = "The token for the Proxmox Virtual Environment API" 9 | sensitive = true 10 | } 11 | 12 | variable "virtual_environment_node_name" { 13 | type = string 14 | description = "The node name for the Proxmox Virtual Environment API" 15 | default = "pve" 16 | } 17 | 18 | variable "datastore_id" { 19 | type = string 20 | description = "Datastore for VM disks" 21 | default = "local-lvm" 22 | } 23 | -------------------------------------------------------------------------------- /proxmox/cluster/ha/groups/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package groups 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | ) 14 | 15 | // Client is an interface for accessing the Proxmox High Availability groups API. 16 | type Client struct { 17 | api.Client 18 | } 19 | 20 | // ExpandPath expands a relative path to the HA groups management API path. 21 | func (c *Client) ExpandPath(path string) string { 22 | return fmt.Sprintf("cluster/ha/groups/%s", path) 23 | } 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: ':sparkles: enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when <...> 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /proxmox/cluster/metrics/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package metrics 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | ) 14 | 15 | // Client is an interface for accessing the Proxmox metrics management API. 16 | type Client struct { 17 | api.Client 18 | } 19 | 20 | // ExpandPath expands a relative path to the Proxmox metrics server management API path. 21 | func (c *Client) ExpandPath(path string) string { 22 | return fmt.Sprintf("cluster/metrics/server/%s", path) 23 | } 24 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_hardware_mapping_pci/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_hardware_mapping_pci" "example" { 2 | comment = "This is a comment" 3 | name = "example" 4 | # The actual map of devices. 5 | map = [ 6 | { 7 | comment = "This is a device specific comment" 8 | id = "8086:5916" 9 | # This is an optional attribute, but causes a mapping to be incomplete when not defined. 10 | iommu_group = 0 11 | node = "pve" 12 | path = "0000:00:02.0" 13 | # This is an optional attribute, but causes a mapping to be incomplete when not defined. 14 | subsystem_id = "8086:2068" 15 | }, 16 | ] 17 | mediated_devices = true 18 | } 19 | -------------------------------------------------------------------------------- /proxmox/cluster/ha/resources/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package resources 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | ) 14 | 15 | // Client is an interface for accessing the Proxmox High Availability resources management API. 16 | type Client struct { 17 | api.Client 18 | } 19 | 20 | // ExpandPath expands a relative path to the HA resources management API path. 21 | func (c *Client) ExpandPath(path string) string { 22 | return fmt.Sprintf("cluster/ha/resources/%s", path) 23 | } 24 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_acl/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_user" "operations_automation" { 2 | comment = "Managed by Terraform" 3 | password = "a-strong-password" 4 | user_id = "operations-automation@pve" 5 | } 6 | 7 | resource "proxmox_virtual_environment_role" "operations_monitoring" { 8 | role_id = "operations-monitoring" 9 | 10 | privileges = [ 11 | "VM.GuestAgent.Audit", 12 | ] 13 | } 14 | 15 | resource "proxmox_virtual_environment_acl" "operations_automation_monitoring" { 16 | user_id = proxmox_virtual_environment_user.operations_automation.user_id 17 | role_id = proxmox_virtual_environment_role.operations_monitoring.role_id 18 | 19 | path = "/vms/1234" 20 | propagate = true 21 | } 22 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_sdn_zone_evpn/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_sdn_zone_evpn" "example" { 2 | id = "evpn1" 3 | nodes = ["pve"] 4 | controller = "evpn-controller1" 5 | vrf_vxlan = 4000 6 | 7 | # Optional attributes 8 | advertise_subnets = true 9 | disable_arp_nd_suppression = false 10 | exit_nodes = ["pve-exit1", "pve-exit2"] 11 | exit_nodes_local_routing = true 12 | primary_exit_node = "pve-exit1" 13 | rt_import = "65000:65000" 14 | mtu = 1450 15 | 16 | # Generic optional attributes 17 | dns = "1.1.1.1" 18 | dns_zone = "example.com" 19 | ipam = "pve" 20 | reverse_dns = "1.1.1.1" 21 | } 22 | -------------------------------------------------------------------------------- /templates/resources/virtual_environment_pool_membership.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: {{.Name}} 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | description: |- 7 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }} 8 | --- 9 | 10 | # {{.Type}}: {{.Name}} 11 | 12 | {{ .Description | trimspace }} 13 | 14 | ~> This resource requires the `Pool.Allocate` permission on the pool path (e.g., `/pool/{poolid}`). 15 | 16 | {{ if .HasExample -}} 17 | ## Example Usage 18 | 19 | {{ codefile "terraform" .ExampleFile }} 20 | {{- end }} 21 | 22 | {{ .SchemaMarkdown | trimspace }} 23 | {{- if .HasImport }} 24 | 25 | ## Import 26 | 27 | Import is supported using the following syntax: 28 | 29 | {{ codefile "shell" .ImportFile }} 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_vm.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_vm 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_vm 9 | 10 | Retrieves information about a specific VM. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_vm" "test_vm" { 16 | node_name = "test" 17 | vm_id = 100 18 | } 19 | ``` 20 | 21 | ## Argument Reference 22 | 23 | - `node_name` - (Required) The node name. 24 | - `vm_id` - (Required) The VM identifier. 25 | 26 | ## Attribute Reference 27 | 28 | - `name` - The virtual machine name. 29 | - `tags` - A list of tags of the VM. 30 | - `status` - The status of the VM. 31 | - `template` - Whether the VM is a template. 32 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_hosts.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_hosts" "example" { 2 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 3 | } 4 | 5 | output "data_proxmox_virtual_environment_hosts_example_addresses" { 6 | value = data.proxmox_virtual_environment_hosts.example.addresses 7 | } 8 | 9 | output "data_proxmox_virtual_environment_hosts_example_digest" { 10 | value = data.proxmox_virtual_environment_hosts.example.digest 11 | } 12 | 13 | output "data_proxmox_virtual_environment_hosts_example_entries" { 14 | value = data.proxmox_virtual_environment_hosts.example.entries 15 | } 16 | 17 | output "data_proxmox_virtual_environment_hosts_example_hostnames" { 18 | value = data.proxmox_virtual_environment_hosts.example.hostnames 19 | } 20 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_hardware_mappings/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_hardware_mappings" "example-dir" { 2 | check_node = "pve" 3 | type = "dir" 4 | } 5 | 6 | data "proxmox_virtual_environment_hardware_mappings" "example-pci" { 7 | check_node = "pve" 8 | type = "pci" 9 | } 10 | 11 | data "proxmox_virtual_environment_hardware_mappings" "example-usb" { 12 | check_node = "pve" 13 | type = "usb" 14 | } 15 | 16 | output "data_proxmox_virtual_environment_hardware_mappings_pci" { 17 | value = data.proxmox_virtual_environment_hardware_mappings.example-pci 18 | } 19 | 20 | output "data_proxmox_virtual_environment_hardware_mappings_usb" { 21 | value = data.proxmox_virtual_environment_hardware_mappings.example-usb 22 | } 23 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_oci_image/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_oci_image" "ubuntu_latest" { 2 | node_name = "pve" 3 | datastore_id = "local" 4 | reference = "docker.io/library/ubuntu:latest" 5 | } 6 | 7 | resource "proxmox_virtual_environment_oci_image" "nginx" { 8 | node_name = "pve" 9 | datastore_id = "local" 10 | reference = "docker.io/library/nginx:alpine" 11 | file_name = "custom_image_name.tar" 12 | } 13 | 14 | resource "proxmox_virtual_environment_oci_image" "debian" { 15 | node_name = "pve" 16 | datastore_id = "local" 17 | reference = "docker.io/library/debian:bookworm" 18 | upload_timeout = 900 19 | overwrite = false 20 | overwrite_unmanaged = true 21 | } 22 | -------------------------------------------------------------------------------- /fwprovider/validators/file.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package validators 8 | 9 | import ( 10 | "regexp" 11 | 12 | "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" 13 | "github.com/hashicorp/terraform-plugin-framework/schema/validator" 14 | ) 15 | 16 | // FileID returns a validator that checks if a string is a valid file ID. 17 | func FileID() validator.String { 18 | return stringvalidator.RegexMatches( 19 | regexp.MustCompile(`^(?i)[a-z\d\-_.]+:([a-z\d\-_]+/)?.+$`), 20 | "must be in the format `:/`", 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_acme_accounts.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_acme_accounts 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | Retrieves the list of ACME accounts. 8 | --- 9 | 10 | # Data Source: proxmox_virtual_environment_acme_accounts 11 | 12 | Retrieves the list of ACME accounts. 13 | 14 | ## Example Usage 15 | 16 | ```terraform 17 | data "proxmox_virtual_environment_acme_accounts" "example" {} 18 | 19 | output "data_proxmox_virtual_environment_acme_accounts" { 20 | value = data.proxmox_virtual_environment_acme_accounts.example.accounts 21 | } 22 | ``` 23 | 24 | 25 | ## Schema 26 | 27 | ### Read-Only 28 | 29 | - `accounts` (Set of String) The identifiers of the ACME accounts. 30 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_metrics_server/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_metrics_server" "influxdb_server" { 2 | name = "example_influxdb_server" 3 | server = "192.168.3.2" 4 | port = 8089 5 | type = "influxdb" 6 | } 7 | 8 | resource "proxmox_virtual_environment_metrics_server" "graphite_server" { 9 | name = "example_graphite_server" 10 | server = "192.168.4.2" 11 | port = 2003 12 | type = "graphite" 13 | } 14 | 15 | resource "proxmox_virtual_environment_metrics_server" "opentelemetry_server" { 16 | name = "example_opentelemetry_server" 17 | server = "192.168.5.2" 18 | port = 4318 19 | type = "opentelemetry" 20 | opentelemetry_proto = "http" 21 | opentelemetry_path = "/v1/metrics" 22 | } 23 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_hosts.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_hosts 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_hosts 9 | 10 | Retrieves all the host entries from a specific node. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_hosts" "first_node_host_entries" { 16 | node_name = "first-node" 17 | } 18 | ``` 19 | 20 | ## Argument Reference 21 | 22 | - `node_name` - (Required) A node name. 23 | 24 | ## Attribute Reference 25 | 26 | - `addresses` - The IP addresses. 27 | - `digest` - The SHA1 digest. 28 | - `entries` - The host entries (conversion of `addresses` and `hostnames` into 29 | objects). 30 | - `hostnames` - The hostnames associated with each of the IP addresses. 31 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_cluster_firewall_security_group.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_cluster_firewall_security_group" "example" { 2 | name = "example-sg" 3 | comment = "Managed by Terraform" 4 | 5 | rule { 6 | type = "in" 7 | action = "ACCEPT" 8 | comment = "Allow FTP" 9 | dest = "192.168.1.5" 10 | dport = "21" 11 | proto = "tcp" 12 | log = "info" 13 | } 14 | 15 | rule { 16 | type = "in" 17 | action = "DROP" 18 | comment = "Drop SSH" 19 | dest = "192.168.1.5" 20 | dport = "22" 21 | proto = "udp" 22 | log = "info" 23 | } 24 | } 25 | 26 | output "resource_proxmox_virtual_environment_cluster_firewall_security_group_example" { 27 | value = proxmox_virtual_environment_cluster_firewall_security_group.example 28 | } 29 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_sdn_zones/data-source.tf: -------------------------------------------------------------------------------- 1 | # List all SDN zones 2 | data "proxmox_virtual_environment_sdn_zones" "all" {} 3 | 4 | # List only EVPN zones 5 | data "proxmox_virtual_environment_sdn_zones" "evpn_only" { 6 | type = "evpn" 7 | } 8 | 9 | # List only Simple zones 10 | data "proxmox_virtual_environment_sdn_zones" "simple_only" { 11 | type = "simple" 12 | } 13 | 14 | output "data_proxmox_virtual_environment_sdn_zones_all" { 15 | value = { 16 | zones = data.proxmox_virtual_environment_sdn_zones.all.zones 17 | } 18 | } 19 | 20 | output "data_proxmox_virtual_environment_sdn_zones_filtered" { 21 | value = { 22 | evpn_zones = data.proxmox_virtual_environment_sdn_zones.evpn_only.zones 23 | simple_zones = data.proxmox_virtual_environment_sdn_zones.simple_only.zones 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/zones/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package zones 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | ) 14 | 15 | // Client is a client for accessing the Proxmox SDN Zones API. 16 | type Client struct { 17 | api.Client 18 | } 19 | 20 | func (c *Client) basePath() string { 21 | return c.Client.ExpandPath("sdn/zones") 22 | } 23 | 24 | // ExpandPath returns the API path for SDN zones. 25 | func (c *Client) ExpandPath(path string) string { 26 | p := c.basePath() 27 | if path != "" { 28 | p = fmt.Sprintf("%s/%s", p, path) 29 | } 30 | 31 | return p 32 | } 33 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_container.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_container 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_container 9 | 10 | Retrieves information about a specific Container. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_container" "test_container" { 16 | node_name = "test" 17 | vm_id = 100 18 | } 19 | ``` 20 | 21 | ## Argument Reference 22 | 23 | - `node_name` - (Required) The node name. 24 | - `vm_id` - (Required) The container identifier. 25 | 26 | ## Attribute Reference 27 | 28 | - `name` - The container name. 29 | - `tags` - A list of tags of the container. 30 | - `status` - The status of the container. 31 | - `template` - Whether the container is a template. 32 | -------------------------------------------------------------------------------- /fwprovider/nodes/vm/rng/model.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package rng 8 | 9 | import ( 10 | "github.com/hashicorp/terraform-plugin-framework/attr" 11 | "github.com/hashicorp/terraform-plugin-framework/types" 12 | ) 13 | 14 | // Model represents the RNG model. 15 | type Model struct { 16 | Source types.String `tfsdk:"source"` 17 | MaxBytes types.Int64 `tfsdk:"max_bytes"` 18 | Period types.Int64 `tfsdk:"period"` 19 | } 20 | 21 | func attributeTypes() map[string]attr.Type { 22 | return map[string]attr.Type{ 23 | "source": types.StringType, 24 | "max_bytes": types.Int64Type, 25 | "period": types.Int64Type, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /fwprovider/nodes/vm/vga/model.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package vga 8 | 9 | import ( 10 | "github.com/hashicorp/terraform-plugin-framework/attr" 11 | "github.com/hashicorp/terraform-plugin-framework/types" 12 | ) 13 | 14 | // Model represents the VGA model. 15 | type Model struct { 16 | Clipboard types.String `tfsdk:"clipboard"` 17 | Type types.String `tfsdk:"type"` 18 | Memory types.Int64 `tfsdk:"memory"` 19 | } 20 | 21 | func attributeTypes() map[string]attr.Type { 22 | return map[string]attr.Type{ 23 | "clipboard": types.StringType, 24 | "type": types.StringType, 25 | "memory": types.Int64Type, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /proxmox/cluster/ha/resources/api.http: -------------------------------------------------------------------------------- 1 | ### Create Proxmox VE API acsess ticket 2 | POST {{host}}:{{port}}/{{api-path-base}}/access/ticket 3 | Accept: application/json 4 | Content-Type: application/x-www-form-urlencoded 5 | 6 | username = {{api-user}} & 7 | password = {{api-user-password}} 8 | 9 | // Save the ticket into a global variable to use in other calls. 10 | > {% 11 | client.global.set("pve_api_access_ticket", response.body.data.ticket); 12 | client.global.set("pve_api_access_ticket_csrf_prevention_token", response.body.data.CSRFPreventionToken); 13 | client.log(`Received Proxmox VE API access ticket "${client.global.get("pve_api_access_ticket")}"`) 14 | %} 15 | 16 | ### List HA resources 17 | GET {{host}}:{{port}}/{{api-path-base}}/cluster/ha/resources 18 | Accept: application/json 19 | Cookie: PVEAuthCookie={{pve_api_access_ticket}} 20 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_sdn_zone_simple/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_sdn_zone_simple" "example" { 2 | id = "simple1" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_sdn_zone_simple" { 6 | value = { 7 | id = data.proxmox_virtual_environment_sdn_zone_simple.example.id 8 | nodes = data.proxmox_virtual_environment_sdn_zone_simple.example.nodes 9 | mtu = data.proxmox_virtual_environment_sdn_zone_simple.example.mtu 10 | dns = data.proxmox_virtual_environment_sdn_zone_simple.example.dns 11 | dns_zone = data.proxmox_virtual_environment_sdn_zone_simple.example.dns_zone 12 | ipam = data.proxmox_virtual_environment_sdn_zone_simple.example.ipam 13 | reverse_dns = data.proxmox_virtual_environment_sdn_zone_simple.example.reverse_dns 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fwprovider/validators/sdn.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package validators 8 | 9 | import ( 10 | "regexp" 11 | 12 | "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" 13 | "github.com/hashicorp/terraform-plugin-framework/schema/validator" 14 | ) 15 | 16 | // SDNID returns a validator that checks if a string is a valid SDN ID (Zone, VNet, Subnet, etc). 17 | func SDNID() []validator.String { 18 | return []validator.String{ 19 | stringvalidator.RegexMatches( 20 | regexp.MustCompile(`^[A-Za-z][A-Za-z0-9]*[A-Za-z0-9]$`), 21 | "must be a valid SDN identifier", 22 | ), 23 | stringvalidator.LengthAtMost(8), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /proxmox/nodes/storage/oci_registry_pull_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | // OCIRegistryPullResponseBody contains the response for an OCI registry pull request. 10 | type OCIRegistryPullResponseBody struct { 11 | TaskID *string `json:"data,omitempty"` 12 | } 13 | 14 | // OCIRegistryPullRequestBody contains the data for an OCI registry pull request. 15 | type OCIRegistryPullRequestBody struct { 16 | FileName *string `json:"filename,omitempty" url:"filename,omitempty"` 17 | Reference *string `json:"reference,omitempty" url:"reference,omitempty"` 18 | Storage *string `json:"storage,omitempty" url:"storage,omitempty"` 19 | } 20 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/subnets/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package subnets 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | ) 14 | 15 | // Client is a client for accessing the Proxmox SDN VNETs API. 16 | type Client struct { 17 | api.Client 18 | } 19 | 20 | func (c *Client) basePath() string { 21 | return c.Client.ExpandPath("subnets") 22 | } 23 | 24 | // ExpandPath expands a relative path to a full VM API path. 25 | func (c *Client) ExpandPath(subnetID string) string { 26 | p := c.basePath() 27 | if subnetID != "" { 28 | p = fmt.Sprintf("%s/%s", p, subnetID) 29 | } 30 | 31 | return p 32 | } 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /example/terraform-provider-* 2 | /pkg/ 3 | /test/ 4 | /website/.vagrant 5 | /website/.bundle 6 | /website/build 7 | /website/node_modules 8 | /website/vendor 9 | 10 | autogenerated/ 11 | bin/ 12 | build/ 13 | cache/ 14 | dist/ 15 | modules-dev/ 16 | 17 | .terraform/ 18 | .vagrant/ 19 | .run/ 20 | .cache/ 21 | .gocache/ 22 | 23 | *~ 24 | *# 25 | *.backup 26 | *.bak 27 | *.dll 28 | *.exe 29 | *.iml 30 | *.lock.hcl 31 | *.log 32 | *.test 33 | *.tfplan 34 | *.tfstate 35 | *.tfstate.lock.info 36 | *.tfvars 37 | *.env 38 | id_rsa.pub 39 | 40 | .*.swp 41 | .DS_Store 42 | .idea 43 | 44 | # Test exclusions 45 | !command/test-fixtures/**/*.tfstate 46 | !command/test-fixtures/**/.terraform/ 47 | 48 | # Binary 49 | terraform-provider-proxmox* 50 | 51 | # VScode / Cursor / Claude 52 | .vscode/settings.json 53 | .cursor/ 54 | .cursorrules 55 | .claude/ 56 | coverage.out 57 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_group.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_group 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_group 9 | 10 | Retrieves information about a specific user group. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_group" "operations_team" { 16 | group_id = "operations-team" 17 | } 18 | ``` 19 | 20 | ## Argument Reference 21 | 22 | - `group_id` - (Required) The group identifier. 23 | 24 | ## Attribute Reference 25 | 26 | - `acl` - The access control list. 27 | - `path` - The path. 28 | - `propagate` - Whether to propagate to child paths. 29 | - `role_id` - The role identifier. 30 | - `comment` - The group comment. 31 | - `members` - The group members as a list with `username@realm` entries. 32 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_pool.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_pool 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_pool 9 | 10 | Retrieves information about a specific resource pool. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_pool" "operations_pool" { 16 | pool_id = "operations" 17 | } 18 | ``` 19 | 20 | ## Argument Reference 21 | 22 | - `pool_id` - (Required) The pool identifier. 23 | 24 | ## Attribute Reference 25 | 26 | - `comment` - The pool comment. 27 | - `members` - The pool members. 28 | - `datastore_id` - The datastore identifier. 29 | - `id` - The member identifier. 30 | - `node_name` - The node name. 31 | - `type` - The member type. 32 | - `vm_id` - The virtual machine identifier. 33 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_node.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_node 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_node 9 | 10 | Retrieves information about node. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_node" "node" {} 16 | ``` 17 | 18 | ## Argument Reference 19 | 20 | - `node_name` - (Required) The node name. 21 | 22 | ## Attribute Reference 23 | 24 | - `cpu_count` - The CPU count on the node. 25 | - `cpu_sockets` - The CPU utilization on the node. 26 | - `cpu_model` - The CPU model on the node. 27 | - `memory_available` - The memory available on the node. 28 | - `memory_used` - The memory used on the node. 29 | - `memory_total` - The total memory on the node. 30 | - `uptime` - The uptime in seconds on the node. 31 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_hagroups.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_hagroups 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | Retrieves the list of High Availability groups. 8 | --- 9 | 10 | # Data Source: proxmox_virtual_environment_hagroups 11 | 12 | Retrieves the list of High Availability groups. 13 | 14 | ## Example Usage 15 | 16 | ```terraform 17 | data "proxmox_virtual_environment_hagroups" "example" {} 18 | 19 | output "data_proxmox_virtual_environment_hagroups" { 20 | value = data.proxmox_virtual_environment_hagroups.example.group_ids 21 | } 22 | ``` 23 | 24 | 25 | ## Schema 26 | 27 | ### Read-Only 28 | 29 | - `group_ids` (Set of String) The identifiers of the High Availability groups. 30 | - `id` (String) The unique identifier of this resource. 31 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_cluster_options/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_cluster_options" "options" { 2 | language = "en" 3 | keyboard = "pl" 4 | email_from = "ged@gont.earthsea" 5 | bandwidth_limit_migration = 555555 6 | bandwidth_limit_default = 666666 7 | max_workers = 5 8 | migration_cidr = "10.0.0.0/8" 9 | migration_type = "secure" 10 | next_id = { 11 | lower = 100 12 | upper = 999999999 13 | } 14 | notify = { 15 | ha_fencing_mode = "never" 16 | ha_fencing_target = "default-matcher" 17 | package_updates = "always" 18 | package_updates_target = "default-matcher" 19 | package_replication = "always" 20 | package_replication_target = "default-matcher" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /proxmox/version/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package version 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 15 | ) 16 | 17 | // Version retrieves the version information. 18 | func (c *Client) Version(ctx context.Context) (*ResponseData, error) { 19 | resBody := &ResponseBody{} 20 | 21 | err := c.DoRequest(ctx, http.MethodGet, "version", nil, resBody) 22 | if err != nil { 23 | return nil, fmt.Errorf("failed to get version information: %w", err) 24 | } 25 | 26 | if resBody.Data == nil { 27 | return nil, api.ErrNoDataObjectInResponse 28 | } 29 | 30 | return resBody.Data, nil 31 | } 32 | -------------------------------------------------------------------------------- /proxmox/nodes/hosts_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package nodes 8 | 9 | // HostsGetResponseBody contains the body from a hosts get response. 10 | type HostsGetResponseBody struct { 11 | Data *HostsGetResponseData `json:"data,omitempty"` 12 | } 13 | 14 | // HostsGetResponseData contains the data from a hosts get response. 15 | type HostsGetResponseData struct { 16 | Data string `json:"data"` 17 | Digest *string `json:"digest,omitempty"` 18 | } 19 | 20 | // HostsUpdateRequestBody contains the body for a hosts update request. 21 | type HostsUpdateRequestBody struct { 22 | Data string `json:"data" url:"data"` 23 | Digest *string `json:"digest,omitempty" url:"digest,omitempty"` 24 | } 25 | -------------------------------------------------------------------------------- /docs/resources/virtual_environment_time.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_time 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Resource: proxmox_virtual_environment_time 9 | 10 | Manages the time for a specific node. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | resource "proxmox_virtual_environment_time" "first_node_time" { 16 | node_name = "first-node" 17 | time_zone = "UTC" 18 | } 19 | ``` 20 | 21 | ## Argument Reference 22 | 23 | - `node_name` - (Required) A node name. 24 | - `time_zone` - (Required) The node's time zone. 25 | 26 | ## Attribute Reference 27 | 28 | - `local_time` - The node's local time. 29 | - `utc_time` - The node's time formatted as UTC. 30 | 31 | ## Import 32 | 33 | Instances can be imported using the `node_name`, e.g., 34 | 35 | ```bash 36 | terraform import proxmox_virtual_environment_time.first_node first-node 37 | ``` 38 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_sdn_zone_vlan/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_sdn_zone_vlan" "example" { 2 | id = "vlan1" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_sdn_zone_vlan" { 6 | value = { 7 | id = data.proxmox_virtual_environment_sdn_zone_vlan.example.id 8 | nodes = data.proxmox_virtual_environment_sdn_zone_vlan.example.nodes 9 | bridge = data.proxmox_virtual_environment_sdn_zone_vlan.example.bridge 10 | mtu = data.proxmox_virtual_environment_sdn_zone_vlan.example.mtu 11 | dns = data.proxmox_virtual_environment_sdn_zone_vlan.example.dns 12 | dns_zone = data.proxmox_virtual_environment_sdn_zone_vlan.example.dns_zone 13 | ipam = data.proxmox_virtual_environment_sdn_zone_vlan.example.ipam 14 | reverse_dns = data.proxmox_virtual_environment_sdn_zone_vlan.example.reverse_dns 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_download_file.tf: -------------------------------------------------------------------------------- 1 | ## Debian and ubuntu image download 2 | 3 | resource "proxmox_virtual_environment_download_file" "ubuntu_24_04_lxc_img" { 4 | content_type = "vztmpl" 5 | datastore_id = "local" 6 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 7 | url = var.ubuntu_24_04_lxc_img_url 8 | upload_timeout = 4444 9 | overwrite_unmanaged = true 10 | } 11 | 12 | resource "proxmox_virtual_environment_download_file" "latest_debian_12_bookworm_qcow2_img" { 13 | content_type = "import" 14 | datastore_id = "local" 15 | file_name = "debian-12-generic-amd64.qcow2" 16 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 17 | url = var.latest_debian_12_bookworm_qcow2_img_url 18 | overwrite = true 19 | overwrite_unmanaged = true 20 | } 21 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/debian-from-storage/main.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_vm" "debian_vm" { 2 | name = "test-debian" 3 | node_name = "pve" 4 | 5 | # should be true if qemu agent is not installed / enabled on the VM 6 | stop_on_destroy = true 7 | 8 | initialization { 9 | user_account { 10 | # do not use this in production, configure your own ssh key instead! 11 | username = "user" 12 | password = "password" 13 | } 14 | } 15 | 16 | disk { 17 | datastore_id = "local-lvm" 18 | # qcow2 image downloaded from https://cloud.debian.org/images/cloud/bookworm/latest/ and renamed to *.img 19 | # the image is not of import type, so provider will use SSH client to import it 20 | file_id = "local:iso/debian-12-genericcloud-amd64.img" 21 | interface = "virtio0" 22 | iothread = true 23 | discard = "on" 24 | size = 20 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /fwprovider/cluster/hardwaremapping/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package hardwaremapping 8 | 9 | import ( 10 | "fmt" 11 | 12 | proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types/hardwaremapping" 13 | ) 14 | 15 | // ErrResourceMessageInvalidPath is the error message for an invalid Linux device path for a hardware mapping of the 16 | // specified type. 17 | // Extracting the message helps to reduce duplicated code and allows to use it in automated unit and acceptance tests. 18 | // 19 | //nolint:gochecknoglobals 20 | var ErrResourceMessageInvalidPath = func(hmType proxmoxtypes.Type) string { 21 | return fmt.Sprintf("not a valid Linux device path for hardware mapping of type %q", hmType) 22 | } 23 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_sdn_zone_vxlan/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_sdn_zone_vxlan" "example" { 2 | id = "vxlan1" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_sdn_zone_vxlan" { 6 | value = { 7 | id = data.proxmox_virtual_environment_sdn_zone_vxlan.example.id 8 | nodes = data.proxmox_virtual_environment_sdn_zone_vxlan.example.nodes 9 | peers = data.proxmox_virtual_environment_sdn_zone_vxlan.example.peers 10 | mtu = data.proxmox_virtual_environment_sdn_zone_vxlan.example.mtu 11 | dns = data.proxmox_virtual_environment_sdn_zone_vxlan.example.dns 12 | dns_zone = data.proxmox_virtual_environment_sdn_zone_vxlan.example.dns_zone 13 | ipam = data.proxmox_virtual_environment_sdn_zone_vxlan.example.ipam 14 | reverse_dns = data.proxmox_virtual_environment_sdn_zone_vxlan.example.reverse_dns 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | name: Release Please 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: {} 8 | 9 | jobs: 10 | release-please: 11 | runs-on: ubuntu-24.04 12 | permissions: 13 | contents: write 14 | steps: 15 | - name: Generate Short Lived OAuth App Token 16 | uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 17 | id: app-token 18 | with: 19 | app-id: "${{ secrets.BOT_APP_ID }}" 20 | private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" 21 | owner: "${{ github.repository_owner }}" 22 | repositories: "${{ github.event.repository.name }}" 23 | 24 | - name: Create / Update Release PR 25 | uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 26 | with: 27 | token: "${{ steps.app-token.outputs.token }}" 28 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_group.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_group" "example" { 2 | acl { 3 | path = "/vms/${proxmox_virtual_environment_vm.example.id}" 4 | role_id = proxmox_virtual_environment_role.example.id 5 | } 6 | 7 | comment = "Managed by Terraform" 8 | group_id = "terraform-provider-proxmox-example" 9 | } 10 | 11 | output "resource_proxmox_virtual_environment_group_example_acl" { 12 | value = proxmox_virtual_environment_group.example.acl 13 | } 14 | 15 | output "resource_proxmox_virtual_environment_group_example_comment" { 16 | value = proxmox_virtual_environment_group.example.comment 17 | } 18 | 19 | output "resource_proxmox_virtual_environment_group_example_id" { 20 | value = proxmox_virtual_environment_group.example.id 21 | } 22 | 23 | output "resource_proxmox_virtual_environment_group_example_members" { 24 | value = proxmox_virtual_environment_group.example.members 25 | } 26 | -------------------------------------------------------------------------------- /docs/resources/virtual_environment_role.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_role 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Resource: proxmox_virtual_environment_role 9 | 10 | Manages a role. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | resource "proxmox_virtual_environment_role" "operations_monitoring" { 16 | role_id = "operations-monitoring" 17 | 18 | privileges = [ 19 | "VM.GuestAgent.Audit", 20 | ] 21 | } 22 | ``` 23 | 24 | ## Argument Reference 25 | 26 | - `privileges` - (Required) The role privileges. 27 | - `role_id` - (Required) The role identifier. 28 | 29 | ## Attribute Reference 30 | 31 | There are no additional attributes available for this resource. 32 | 33 | ## Import 34 | 35 | Instances can be imported using the `role_id`, e.g., 36 | 37 | ```bash 38 | terraform import proxmox_virtual_environment_role.operations_monitoring operations-monitoring 39 | ``` 40 | -------------------------------------------------------------------------------- /proxmox/nodes/apt/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package apt 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/apt/repositories" 14 | ) 15 | 16 | // Client is an interface for accessing the Proxmox cluster API. 17 | type Client struct { 18 | api.Client 19 | } 20 | 21 | // ExpandPath expands a relative path to a full cluster API path. 22 | func (c *Client) ExpandPath(path string) string { 23 | return c.Client.ExpandPath(fmt.Sprintf("apt/%s", path)) 24 | } 25 | 26 | // Repositories returns a client for managing APT repositories. 27 | func (c *Client) Repositories() *repositories.Client { 28 | return &repositories.Client{Client: c} 29 | } 30 | -------------------------------------------------------------------------------- /utils/io_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package utils 8 | 9 | import ( 10 | "fmt" 11 | "testing" 12 | 13 | "github.com/stretchr/testify/assert" 14 | ) 15 | 16 | func TestCloseOrLogError(t *testing.T) { 17 | t.Parallel() 18 | 19 | f := CloseOrLogError(t.Context()) 20 | 21 | c := &testCloser{} 22 | b := &badCloser{} 23 | 24 | func() { 25 | defer f(c) 26 | defer f(b) 27 | 28 | assert.False(t, c.isClosed) 29 | }() 30 | 31 | assert.True(t, c.isClosed) 32 | } 33 | 34 | type testCloser struct { 35 | isClosed bool 36 | } 37 | 38 | func (t *testCloser) Close() error { 39 | t.isClosed = true 40 | return nil 41 | } 42 | 43 | type badCloser struct{} 44 | 45 | func (t *badCloser) Close() error { 46 | return fmt.Errorf("bad") 47 | } 48 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_users.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_users 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_users 9 | 10 | Retrieves information about all the available users. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_users" "available_users" {} 16 | ``` 17 | 18 | ## Argument Reference 19 | 20 | There are no arguments available for this data source. 21 | 22 | ## Attribute Reference 23 | 24 | - `comments` - The user comments. 25 | - `emails` - The users' email addresses. 26 | - `enabled` - Whether a user account is enabled. 27 | - `expiration_dates` - The user accounts' expiration dates (RFC 3339). 28 | - `first_names` - The users' first names. 29 | - `groups` - The users' groups. 30 | - `keys` - The users' keys. 31 | - `last_names` - The users' last names. 32 | - `user_ids` - The user identifiers. 33 | -------------------------------------------------------------------------------- /examples/resources/proxmox_virtual_environment_network_linux_bridge/resource.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_network_linux_bridge" "vmbr99" { 2 | depends_on = [ 3 | proxmox_virtual_environment_network_linux_vlan.vlan99 4 | ] 5 | 6 | node_name = "pve" 7 | name = "vmbr99" 8 | 9 | address = "99.99.99.99/16" 10 | 11 | comment = "vmbr99 comment" 12 | 13 | ports = [ 14 | # Network (or VLAN) interfaces to attach to the bridge, specified by their interface name 15 | # (e.g. "ens18.99" for VLAN 99 on interface ens18). 16 | # For VLAN interfaces with custom names, use the interface name without the VLAN tag, e.g. "vlan_lab" 17 | "ens18.99" 18 | ] 19 | } 20 | 21 | resource "proxmox_virtual_environment_network_linux_vlan" "vlan99" { 22 | node_name = "pve" 23 | name = "ens18.99" 24 | 25 | ## or alternatively, use custom name: 26 | # name = "vlan_lab" 27 | # interface = "eno0" 28 | # vlan = 98 29 | } 30 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.25.5@sha256:36b4f45d2874905b9e8573b783292629bcb346d0a70d8d7150b6df545234818f 2 | 3 | ARG GOLANGCI_LINT_VERSION=2.7.2 # renovate: depName=golangci/golangci-lint datasource=github-releases 4 | 5 | RUN apt update && apt upgrade -y && \ 6 | apt-get install --no-install-recommends -y ca-certificates curl gnupg lsb-release jq zsh neovim gh && \ 7 | chsh -s $(which zsh) && \ 8 | sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v${GOLANGCI_LINT_VERSION} 12 | 13 | 14 | RUN curl --proto '=https' --tlsv1.2 -fsSL https://get.opentofu.org/install-opentofu.sh -o install-opentofu.sh && \ 15 | chmod +x install-opentofu.sh && \ 16 | ./install-opentofu.sh --install-method deb && \ 17 | rm -f install-opentofu.sh 18 | -------------------------------------------------------------------------------- /proxmox/cluster/acme/account/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package account 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/tasks" 14 | ) 15 | 16 | // Client is an interface for accessing the Proxmox ACME management API. 17 | type Client struct { 18 | api.Client 19 | } 20 | 21 | // ExpandPath expands a relative path to the Proxmox ACME management API path. 22 | func (c *Client) ExpandPath(path string) string { 23 | return fmt.Sprintf("cluster/acme/account/%s", path) 24 | } 25 | 26 | // Tasks returns a client for managing ACME account tasks. 27 | func (c *Client) Tasks() *tasks.Client { 28 | return &tasks.Client{ 29 | Client: c.Client, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fwprovider/validators/hardware_mapping.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package validators 8 | 9 | import ( 10 | "github.com/hashicorp/terraform-plugin-framework/schema/validator" 11 | 12 | proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types/hardwaremapping" 13 | ) 14 | 15 | const ( 16 | // HardwareMappingDeviceIDValidatorErrMessage is the error message when the validation fails. 17 | HardwareMappingDeviceIDValidatorErrMessage = `value must be a valid hardware mapping device ID, e.g. "8086:5916"` 18 | ) 19 | 20 | // HardwareMappingDeviceIDValidator validates a hardware mapping device ID. 21 | func HardwareMappingDeviceIDValidator() validator.String { 22 | return NewParseValidator(proxmoxtypes.ParseDeviceID, HardwareMappingDeviceIDValidatorErrMessage) 23 | } 24 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/applier/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package applier 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 11 | "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/tasks" 12 | ) 13 | 14 | // Client is a client for accessing the Proxmox SDN Apply API. 15 | type Client struct { 16 | api.Client 17 | } 18 | 19 | func (c *Client) basePath() string { 20 | return c.Client.ExpandPath("sdn") 21 | } 22 | 23 | // ExpandPath returns the API path for cluster-wide SDN apply. 24 | func (c *Client) ExpandPath(_ string) string { 25 | return c.basePath() 26 | } 27 | 28 | // Tasks returns a client for managing SDN tasks. 29 | func (c *Client) Tasks() *tasks.Client { 30 | return &tasks.Client{ 31 | Client: c.Client, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /templates/resources/virtual_environment_download_file.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: {{.Name}} 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | description: |- 7 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }} 8 | --- 9 | 10 | # {{.Type}}: {{.Name}} 11 | 12 | {{ .Description | trimspace }} 13 | 14 | ~> Besides the `Datastore.AllocateTemplate` privilege, this resource requires both the `Sys.Audit` and `Sys.Modify` privileges.

15 | For more details, see the [`download-url`](https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/storage/{storage}/download-url) API documentation under the "Required permissions" section. 16 | 17 | {{ if .HasExample -}} 18 | ## Example Usage 19 | 20 | {{ codefile "terraform" .ExampleFile }} 21 | {{- end }} 22 | 23 | {{ .SchemaMarkdown | trimspace }} 24 | {{- if .HasImport }} 25 | 26 | ## Import 27 | 28 | Import is supported using the following syntax: 29 | 30 | {{ codefile "shell" .ImportFile }} 31 | {{- end }} 32 | -------------------------------------------------------------------------------- /example/resource_virtual_environment_hosts.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_hosts" "example" { 2 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 3 | 4 | dynamic "entry" { 5 | for_each = data.proxmox_virtual_environment_hosts.example.entries 6 | 7 | content { 8 | address = entry.value.address 9 | hostnames = entry.value.hostnames 10 | } 11 | } 12 | } 13 | 14 | output "resource_proxmox_virtual_environment_hosts_example_addresses" { 15 | value = proxmox_virtual_environment_hosts.example.addresses 16 | } 17 | 18 | output "resource_proxmox_virtual_environment_hosts_example_digest" { 19 | value = proxmox_virtual_environment_hosts.example.digest 20 | } 21 | 22 | output "resource_proxmox_virtual_environment_hosts_example_entries" { 23 | value = proxmox_virtual_environment_hosts.example.entries 24 | } 25 | 26 | output "resource_proxmox_virtual_environment_hosts_example_hostnames" { 27 | value = proxmox_virtual_environment_hosts.example.hostnames 28 | } 29 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_nodes.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_nodes 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_nodes 9 | 10 | Retrieves information about all available nodes. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_nodes" "available_nodes" {} 16 | ``` 17 | 18 | ## Argument Reference 19 | 20 | There are no arguments available for this data source. 21 | 22 | ## Attribute Reference 23 | 24 | - `cpu_count` - The CPU count for each node. 25 | - `cpu_utilization` - The CPU utilization on each node. 26 | - `memory_available` - The memory available on each node. 27 | - `memory_used` - The memory used on each node. 28 | - `names` - The node names. 29 | - `online` - Whether a node is online. 30 | - `ssl_fingerprints` - The SSL fingerprint for each node. 31 | - `support_levels` - The support level for each node. 32 | - `uptime` - The uptime in seconds for each node. 33 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/applier/applier.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package applier 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | ) 14 | 15 | // ApplyConfig triggers a cluster-wide SDN apply via PUT /cluster/sdn. 16 | func (c *Client) ApplyConfig(ctx context.Context) error { 17 | resBody := &ApplyResponseBody{} 18 | 19 | if err := c.DoRequest(ctx, http.MethodPut, c.ExpandPath(""), nil, resBody); err != nil { 20 | return fmt.Errorf("error applying SDN configuration: %w", err) 21 | } 22 | 23 | if resBody.Data == nil || *resBody.Data == "" { 24 | return fmt.Errorf("SDN apply did not return a task UPID") 25 | } 26 | 27 | err := c.Tasks().WaitForTask(ctx, *resBody.Data) 28 | if err != nil { 29 | return fmt.Errorf("error waiting for SDN apply: %w", err) 30 | } 31 | 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /fwprovider/types/stringset/options.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package stringset 8 | 9 | type options struct { 10 | separator string 11 | } 12 | 13 | type Option struct { 14 | apply func(*options) 15 | } 16 | 17 | func defaultOptions(opts ...Option) options { 18 | opt := options{ 19 | separator: ";", 20 | } 21 | 22 | for _, o := range opts { 23 | o.apply(&opt) 24 | } 25 | 26 | return opt 27 | } 28 | 29 | // WithSeparator sets the separator for the string set value. 30 | // For future use, to set the separator to a different value than the default ";". 31 | // Would allow us to replace types.CustomCommaSeparatedList custom type that can only handle commas. 32 | func WithSeparator(separator string) Option { 33 | return Option{ 34 | apply: func(o *options) { 35 | o.separator = separator 36 | }, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /.github/workflows/code-quality.yml: -------------------------------------------------------------------------------- 1 | name: Qodana 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | types: [opened, synchronize] 9 | 10 | jobs: 11 | qodana: 12 | runs-on: ubuntu-24.04 13 | if: github.event.pull_request.head.repo.owner.login == 'bpg' || github.event.ref == 'refs/heads/main' 14 | permissions: 15 | contents: write 16 | pull-requests: write 17 | checks: write 18 | steps: 19 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 20 | with: 21 | ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit 22 | fetch-depth: 0 # a full history is required for pull request analysis 23 | - name: 'Qodana Scan' 24 | uses: JetBrains/qodana-action@99ec27a55aaaf5ba2fd7e5816e66231caed7a72a # v2025.2.4 25 | with: 26 | post-pr-comment: false 27 | env: 28 | QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} 29 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/centos-qcow2/main.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_vm" "centos_vm" { 2 | name = "test-centos" 3 | node_name = "pve" 4 | 5 | # should be true if qemu agent is not installed / enabled on the VM 6 | stop_on_destroy = true 7 | 8 | initialization { 9 | user_account { 10 | # do not use this in production, configure your own ssh key instead! 11 | username = "user" 12 | password = "password" 13 | } 14 | } 15 | 16 | disk { 17 | datastore_id = "local-lvm" 18 | import_from = proxmox_virtual_environment_download_file.centos_cloud_image.id 19 | interface = "virtio0" 20 | iothread = true 21 | discard = "on" 22 | size = 20 23 | } 24 | } 25 | 26 | resource "proxmox_virtual_environment_download_file" "centos_cloud_image" { 27 | content_type = "import" 28 | datastore_id = "local" 29 | node_name = "pve" 30 | url = "https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-latest.x86_64.qcow2" 31 | } 32 | -------------------------------------------------------------------------------- /proxmox/nodes/query_url_metadata.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package nodes 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 15 | ) 16 | 17 | // GetQueryURLMetadata retrieves the URL filename details for a node. 18 | func (c *Client) GetQueryURLMetadata( 19 | ctx context.Context, 20 | d *QueryURLMetadataGetRequestBody, 21 | ) (*QueryURLMetadataGetResponseData, error) { 22 | resBody := &QueryURLMetadataGetResponseBody{} 23 | 24 | err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("query-url-metadata"), d, resBody) 25 | if err != nil { 26 | return nil, fmt.Errorf("error retrieving URL metadata for %q: %w", d.URL, err) 27 | } 28 | 29 | if resBody.Data == nil { 30 | return nil, api.ErrNoDataObjectInResponse 31 | } 32 | 33 | return resBody.Data, nil 34 | } 35 | -------------------------------------------------------------------------------- /proxmox/nodes/storage/status.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 15 | ) 16 | 17 | // GetDatastoreStatus gets status information for a given datastore. 18 | func (c *Client) GetDatastoreStatus( 19 | ctx context.Context, 20 | ) (*DatastoreGetStatusResponseData, error) { 21 | resBody := &DatastoreGetStatusResponseBody{} 22 | 23 | err := c.DoRequest( 24 | ctx, 25 | http.MethodGet, 26 | c.ExpandPath("status"), 27 | nil, 28 | resBody, 29 | ) 30 | if err != nil { 31 | return nil, fmt.Errorf("error retrieving status for datastore %s: %w", c.StorageName, err) 32 | } 33 | 34 | if resBody.Data == nil { 35 | return nil, api.ErrNoDataObjectInResponse 36 | } 37 | 38 | return resBody.Data, nil 39 | } 40 | -------------------------------------------------------------------------------- /examples/guides/cloud-init/custom/cloud-config.tf: -------------------------------------------------------------------------------- 1 | data "local_file" "ssh_public_key" { 2 | filename = "./id_rsa.pub" 3 | } 4 | 5 | resource "proxmox_virtual_environment_file" "user_data_cloud_config" { 6 | content_type = "snippets" 7 | datastore_id = "local" 8 | node_name = "pve" 9 | 10 | source_raw { 11 | data = <<-EOF 12 | #cloud-config 13 | hostname: test-ubuntu 14 | timezone: America/Toronto 15 | users: 16 | - default 17 | - name: ubuntu 18 | groups: 19 | - sudo 20 | shell: /bin/bash 21 | ssh_authorized_keys: 22 | - ${trimspace(data.local_file.ssh_public_key.content)} 23 | sudo: ALL=(ALL) NOPASSWD:ALL 24 | package_update: true 25 | packages: 26 | - qemu-guest-agent 27 | - net-tools 28 | - curl 29 | runcmd: 30 | - systemctl enable qemu-guest-agent 31 | - systemctl start qemu-guest-agent 32 | - echo "done" > /tmp/cloud-config.done 33 | EOF 34 | 35 | file_name = "user-data-cloud-config.yaml" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_containers.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_containers" "example" { 2 | depends_on = [proxmox_virtual_environment_container.example] 3 | tags = ["example"] 4 | 5 | lifecycle { 6 | postcondition { 7 | condition = length(self.containers) == 1 8 | error_message = "Only 1 container should have this tag" 9 | } 10 | } 11 | } 12 | 13 | data "proxmox_virtual_environment_containers" "template_example" { 14 | depends_on = [proxmox_virtual_environment_container.example] 15 | tags = ["example"] 16 | 17 | filter { 18 | name = "template" 19 | values = [false] 20 | } 21 | 22 | filter { 23 | name = "status" 24 | values = ["running"] 25 | } 26 | } 27 | 28 | output "proxmox_virtual_environment_containers_example" { 29 | value = data.proxmox_virtual_environment_containers.example.containers 30 | } 31 | 32 | output "proxmox_virtual_environment_template_containers_example" { 33 | value = data.proxmox_virtual_environment_containers.template_example.containers 34 | } 35 | -------------------------------------------------------------------------------- /proxmox/api/authenticator.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package api 8 | 9 | import ( 10 | "context" 11 | "net/http" 12 | ) 13 | 14 | // Authenticator is an interface for adding authentication data to a request. 15 | // The authenticator is also aware of the authentication context, e.g. if it 16 | // is configured to use the root user. 17 | type Authenticator interface { 18 | // IsRoot returns true if the authenticator is configured to use the root 19 | IsRoot(ctx context.Context) bool 20 | 21 | // IsRootTicket returns true if the authenticator is configured to use the root directly using a login ticket. 22 | // (root using token is weaker, cannot change VM arch) 23 | IsRootTicket(ctx context.Context) bool 24 | 25 | // AuthenticateRequest adds authentication data to a new request. 26 | AuthenticateRequest(ctx context.Context, req *http.Request) error 27 | } 28 | -------------------------------------------------------------------------------- /examples/guides/clone-vm/cloud-config.tf: -------------------------------------------------------------------------------- 1 | data "local_file" "ssh_public_key" { 2 | filename = "./id_rsa.pub" 3 | } 4 | 5 | resource "proxmox_virtual_environment_file" "user_data_cloud_config" { 6 | content_type = "snippets" 7 | datastore_id = "local" 8 | node_name = var.virtual_environment_node_name 9 | 10 | source_raw { 11 | data = <<-EOF 12 | #cloud-config 13 | hostname: test-ubuntu 14 | timezone: America/Toronto 15 | users: 16 | - default 17 | - name: ubuntu 18 | groups: 19 | - sudo 20 | shell: /bin/bash 21 | ssh_authorized_keys: 22 | - ${trimspace(data.local_file.ssh_public_key.content)} 23 | sudo: ALL=(ALL) NOPASSWD:ALL 24 | package_update: true 25 | packages: 26 | - qemu-guest-agent 27 | - net-tools 28 | - curl 29 | runcmd: 30 | - systemctl enable qemu-guest-agent 31 | - systemctl start qemu-guest-agent 32 | - echo "done" > /tmp/cloud-config.done 33 | EOF 34 | 35 | file_name = "user-data-cloud-config.yaml" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /proxmox/cluster/mapping/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | This Source Code Form is subject to the terms of the Mozilla Public 3 | License, v. 2.0. If a copy of the MPL was not distributed with this 4 | file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package mapping 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types/hardwaremapping" 14 | ) 15 | 16 | // Client is an interface for accessing the Proxmox cluster mapping API. 17 | type Client struct { 18 | api.Client 19 | } 20 | 21 | func (c *Client) basePath() string { 22 | return c.Client.ExpandPath("mapping") 23 | } 24 | 25 | // ExpandPath expands a relative path to a full hardware mapping API path. 26 | func (c *Client) ExpandPath(hmType proxmoxtypes.Type, path string) string { 27 | ep := c.basePath() 28 | if hmType.String() != "" { 29 | ep = fmt.Sprintf("%s/%s", ep, hmType.String()) 30 | } 31 | 32 | if path != "" { 33 | ep = fmt.Sprintf("%s/%s", ep, path) 34 | } 35 | 36 | return ep 37 | } 38 | -------------------------------------------------------------------------------- /docs/resources/virtual_environment_pool.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_pool 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Resource: proxmox_virtual_environment_pool 9 | 10 | Manages a resource pool. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | resource "proxmox_virtual_environment_pool" "operations_pool" { 16 | comment = "Managed by Terraform" 17 | pool_id = "operations-pool" 18 | } 19 | ``` 20 | 21 | ## Argument Reference 22 | 23 | - `comment` - (Optional) The pool comment. 24 | - `pool_id` - (Required) The pool identifier. 25 | 26 | ## Attribute Reference 27 | 28 | - `members` - The pool members. 29 | - `datastore_id` - The datastore identifier. 30 | - `id` - The member identifier. 31 | - `node_name` - The node name. 32 | - `type` - The member type. 33 | - `vm_id` - The virtual machine identifier. 34 | 35 | ## Import 36 | 37 | Instances can be imported using the `pool_id`, e.g., 38 | 39 | ```bash 40 | terraform import proxmox_virtual_environment_pool.operations_pool operations-pool 41 | ``` 42 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_vms.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_vms" "example" { 2 | depends_on = [proxmox_virtual_environment_vm.example] 3 | tags = ["ubuntu"] 4 | 5 | lifecycle { 6 | postcondition { 7 | condition = length(self.vms) == 1 8 | error_message = "Only 1 vm should have this tag" 9 | } 10 | } 11 | } 12 | 13 | data "proxmox_virtual_environment_vms" "template_example" { 14 | depends_on = [proxmox_virtual_environment_vm.example] 15 | tags = ["ubuntu"] 16 | 17 | filter { 18 | name = "template" 19 | values = [false] 20 | } 21 | 22 | filter { 23 | name = "status" 24 | values = ["running"] 25 | } 26 | 27 | filter { 28 | name = "name" 29 | regex = true 30 | values = [".*ubuntu.*"] 31 | } 32 | } 33 | 34 | output "proxmox_virtual_environment_vms_example" { 35 | value = data.proxmox_virtual_environment_vms.example.vms 36 | } 37 | 38 | output "proxmox_virtual_environment_template_vms_example" { 39 | value = data.proxmox_virtual_environment_vms.template_example.vms 40 | } 41 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Run Acceptance Tests", 6 | "type": "go", 7 | "request": "launch", 8 | "mode": "test", 9 | "program": "${workspaceFolder}/fwprovider/test", 10 | "envFile": "${workspaceFolder}/testacc.env", 11 | "args": ["-test.v", "-test.timeout", "120s"] 12 | }, 13 | { 14 | "name": "Debug Acceptance Tests", 15 | "type": "go", 16 | "request": "launch", 17 | "mode": "test", 18 | "program": "${workspaceFolder}/fwprovider/test", 19 | "envFile": "${workspaceFolder}/testacc.env", 20 | "args": ["-debug", "-test.v", "-test.timeout", "120s"] 21 | 22 | }, 23 | { 24 | "name": "Debug Provider", 25 | "type": "go", 26 | "request": "launch", 27 | "mode": "auto", 28 | "program": "./", 29 | "args": ["-debug"] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_user.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_user 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Data Source: proxmox_virtual_environment_user 9 | 10 | Retrieves information about a specific user. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | data "proxmox_virtual_environment_user" "operations_user" { 16 | user_id = "operation@pam" 17 | } 18 | ``` 19 | 20 | ## Argument Reference 21 | 22 | - `user_id` - (Required) The user identifier. 23 | 24 | ## Attribute Reference 25 | 26 | - `acl` - The access control list. 27 | - `path` - The path. 28 | - `propagate` - Whether to propagate to child paths. 29 | - `role_id` - The role identifier. 30 | - `comment` - The user comment. 31 | - `email` - The user's email address. 32 | - `enabled` - Whether the user account is enabled. 33 | - `expiration_date` - The user account's expiration date (RFC 3339). 34 | - `first_name` - The user's first name. 35 | - `groups` - The user's groups. 36 | - `keys` - The user's keys. 37 | - `last_name` - The user's last name. 38 | -------------------------------------------------------------------------------- /docs/resources/virtual_environment_group.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_group 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Resource: proxmox_virtual_environment_group 9 | 10 | Manages a user group. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | resource "proxmox_virtual_environment_group" "operations_team" { 16 | comment = "Managed by Terraform" 17 | group_id = "operations-team" 18 | } 19 | ``` 20 | 21 | ## Argument Reference 22 | 23 | - `acl` - (Optional) The access control list (multiple blocks supported). 24 | - `path` - The path. 25 | - `propagate` - Whether to propagate to child paths. 26 | - `role_id` - The role identifier. 27 | - `comment` - (Optional) The group comment. 28 | - `group_id` - (Required) The group identifier. 29 | 30 | ## Attribute Reference 31 | 32 | - `members` - The group members as a list of `username@realm` entries 33 | 34 | ## Import 35 | 36 | Instances can be imported using the `group_id`, e.g., 37 | 38 | ```bash 39 | terraform import proxmox_virtual_environment_group.operations_team operations-team 40 | ``` 41 | -------------------------------------------------------------------------------- /proxmox/api/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package api 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | // Error is a sentinel error type for API errors. 14 | type Error string 15 | 16 | func (err Error) Error() string { 17 | return string(err) 18 | } 19 | 20 | // ErrNoDataObjectInResponse is returned when the server does not include a data object in the response. 21 | const ErrNoDataObjectInResponse Error = "the server did not include a data object in the response" 22 | 23 | // ErrResourceDoesNotExist is returned when the requested resource does not exist. 24 | const ErrResourceDoesNotExist Error = "the requested resource does not exist" 25 | 26 | // HTTPError is a generic error type for HTTP errors. 27 | type HTTPError struct { 28 | Code int 29 | Message string 30 | } 31 | 32 | func (err HTTPError) Error() string { 33 | return fmt.Sprintf("received an HTTP %d response - Reason: %s", err.Code, err.Message) 34 | } 35 | -------------------------------------------------------------------------------- /proxmoxtf/datasource/pools_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package datasource 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmoxtf/test" 15 | ) 16 | 17 | // TestPoolsInstantiation tests whether the Pools instance can be instantiated. 18 | func TestPoolsInstantiation(t *testing.T) { 19 | t.Parallel() 20 | 21 | s := Pools() 22 | if s == nil { 23 | t.Fatalf("Cannot instantiate Pools") 24 | } 25 | } 26 | 27 | // TestPoolsSchema tests the Pools schema. 28 | func TestPoolsSchema(t *testing.T) { 29 | t.Parallel() 30 | 31 | s := Pools().Schema 32 | 33 | test.AssertComputedAttributes(t, s, []string{ 34 | mkDataSourceVirtualEnvironmentPoolsPoolIDs, 35 | }) 36 | 37 | test.AssertValueTypes(t, s, map[string]schema.ValueType{ 38 | mkDataSourceVirtualEnvironmentPoolsPoolIDs: schema.TypeList, 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /proxmox/nodes/storage/storage.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | "sort" 14 | 15 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 16 | ) 17 | 18 | // ListDatastores retrieves a list of nodes. 19 | func (c *Client) ListDatastores( 20 | ctx context.Context, 21 | d *DatastoreListRequestBody, 22 | ) ([]*DatastoreListResponseData, error) { 23 | resBody := &DatastoreListResponseBody{} 24 | 25 | err := c.DoRequest( 26 | ctx, 27 | http.MethodGet, 28 | c.basePath(), 29 | d, 30 | resBody, 31 | ) 32 | if err != nil { 33 | return nil, fmt.Errorf("error retrieving datastores: %w", err) 34 | } 35 | 36 | if resBody.Data == nil { 37 | return nil, api.ErrNoDataObjectInResponse 38 | } 39 | 40 | sort.Slice(resBody.Data, func(i, j int) bool { 41 | return resBody.Data[i].ID < resBody.Data[j].ID 42 | }) 43 | 44 | return resBody.Data, nil 45 | } 46 | -------------------------------------------------------------------------------- /proxmox/storage/storage_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/types" 11 | ) 12 | 13 | // DatastoreGetResponseBody contains the body from a datastore get response. 14 | type DatastoreGetResponseBody struct { 15 | Data *DatastoreGetResponseData `json:"data,omitempty"` 16 | } 17 | 18 | // DatastoreGetResponseData contains the data from a datastore get response. 19 | type DatastoreGetResponseData struct { 20 | Content types.CustomCommaSeparatedList `json:"content,omitempty" url:"content,omitempty,comma"` 21 | Digest *string `json:"digest,omitempty"` 22 | Path *string `json:"path,omitempty"` 23 | Shared *types.CustomBool `json:"shared,omitempty"` 24 | Storage *string `json:"storage,omitempty"` 25 | Type *string `json:"type,omitempty"` 26 | } 27 | -------------------------------------------------------------------------------- /proxmox/cluster/sdn/vnets/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package vnets 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/sdn/subnets" 14 | ) 15 | 16 | // Client is a client for accessing the Proxmox SDN VNETs API. 17 | type Client struct { 18 | api.Client 19 | 20 | ID string 21 | } 22 | 23 | func (c *Client) basePath() string { 24 | return c.Client.ExpandPath("sdn/vnets") 25 | } 26 | 27 | // ExpandPath expands a relative path to a full VM API path. 28 | func (c *Client) ExpandPath(path string) string { 29 | p := fmt.Sprintf("%s/%s", c.basePath(), c.ID) 30 | if path != "" { 31 | p = fmt.Sprintf("%s/%s", p, path) 32 | } 33 | 34 | return p 35 | } 36 | 37 | // Subnets returns a client for managing the SDN Vnet's subnets. 38 | func (c *Client) Subnets() *subnets.Client { 39 | return &subnets.Client{ 40 | Client: c, 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/guides/cloud-image/ubuntu-img/main.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_vm" "ubuntu_vm" { 2 | name = "test-ubuntu" 3 | node_name = "pve" 4 | 5 | # should be true if qemu agent is not installed / enabled on the VM 6 | stop_on_destroy = true 7 | 8 | initialization { 9 | user_account { 10 | # do not use this in production, configure your own ssh key instead! 11 | username = "user" 12 | password = "password" 13 | } 14 | } 15 | 16 | disk { 17 | datastore_id = "local-lvm" 18 | import_from = proxmox_virtual_environment_download_file.ubuntu_cloud_image.id 19 | interface = "virtio0" 20 | iothread = true 21 | discard = "on" 22 | size = 20 23 | } 24 | } 25 | 26 | resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" { 27 | content_type = "import" 28 | datastore_id = "local" 29 | node_name = "pve" 30 | url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" 31 | # need to rename the file to *.qcow2 to indicate the actual file format for import 32 | file_name = "jammy-server-cloudimg-amd64.qcow2" 33 | } 34 | -------------------------------------------------------------------------------- /fwprovider/validators/i18n.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package validators 8 | 9 | import ( 10 | "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" 11 | "github.com/hashicorp/terraform-plugin-framework/schema/validator" 12 | ) 13 | 14 | // LanguageValidator returns a new validator for language codes. 15 | func LanguageValidator() validator.String { 16 | return stringvalidator.OneOf([]string{ 17 | `ca`, `da`, `de`, `en`, `es`, `eu`, `fa`, `fr`, `he`, `it`, `ja`, `nb`, 18 | `nn`, `pl`, `pt_BR`, `ru`, `sl`, `sv`, `tr`, `zh_CN`, `zh_TW`, 19 | }...) 20 | } 21 | 22 | // KeyboardLayoutValidator returns a new validator for keyboard layouts. 23 | func KeyboardLayoutValidator() validator.String { 24 | return stringvalidator.OneOf([]string{ 25 | `de`, `de-ch`, `da`, `en-gb`, `en-us`, `es`, `fi`, `fr`, `fr-be`, `fr-ca`, `fr-ch`, 26 | `hu`, `is`, `it`, `ja`, `lt`, `mk`, `nl`, `no`, `pl`, `pt`, `pt-br`, `sv`, `sl`, `tr`, 27 | }...) 28 | } 29 | -------------------------------------------------------------------------------- /proxmoxtf/resource/validators/network_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package validators 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestMACAddress(t *testing.T) { 16 | t.Parallel() 17 | 18 | tests := []struct { 19 | name string 20 | value string 21 | valid bool 22 | }{ 23 | {"empty", "", true}, 24 | {"invalid", "invalid", false}, 25 | {"invalid: no dashes", "38-f9-d3-4b-f5-51", false}, 26 | {"valid", "38:f9:d3:4b:f5:51", true}, 27 | {"valid", "38:F9:D3:4B:F5:51", true}, 28 | {"valid", "00:15:5d:00:09:03", true}, 29 | } 30 | 31 | for _, tt := range tests { 32 | t.Run(tt.name, func(t *testing.T) { 33 | t.Parallel() 34 | 35 | f := MACAddress() 36 | res := f(tt.value, nil) 37 | 38 | if tt.valid { 39 | require.Empty(t, res, "validate: '%s'", tt.value) 40 | } else { 41 | require.NotEmpty(t, res, "validate: '%s'", tt.value) 42 | } 43 | }) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /templates/guides/cloud-image.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | page_title: "Create a VM from a Cloud Image" 4 | subcategory: Guides 5 | description: |- 6 | This guide explains how to create a VM from a cloud image. 7 | --- 8 | 9 | # Create a VM from a Cloud Image 10 | 11 | ## Download a public cloud image from URL 12 | 13 | Example of how to create a CentOS 8 VM from a "generic cloud" `qcow2` image. CentOS 8 images are available at [cloud.centos.org](https://cloud.centos.org/centos/8-stream/x86_64/images/): 14 | 15 | {{ codefile "terraform" "examples/guides/cloud-image/centos-qcow2/main.tf" }} 16 | 17 | Ubuntu cloud images are available at [cloud-images.ubuntu.com](https://cloud-images.ubuntu.com/). Ubuntu cloud images are in `qcow2` format as well, but stored with `.img` extension, so they can be directly uploaded to Proxmox without renaming. 18 | 19 | {{ codefile "terraform" "examples/guides/cloud-image/ubuntu-img/main.tf" }} 20 | 21 | ## Create a VM from an existing image on Proxmox 22 | 23 | If you already have a cloud image on Proxmox, you can use it to create a VM: 24 | 25 | {{ codefile "terraform" "examples/guides/cloud-image/debian-from-storage/main.tf" }} 26 | -------------------------------------------------------------------------------- /fwprovider/nodes/vm/cdrom/model.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package cdrom 8 | 9 | import ( 10 | "github.com/hashicorp/terraform-plugin-framework/attr" 11 | "github.com/hashicorp/terraform-plugin-framework/types" 12 | 13 | "github.com/bpg/terraform-provider-proxmox/proxmox/helpers/ptr" 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms" 15 | ) 16 | 17 | // Model represents the CD-ROM model. 18 | type Model struct { 19 | FileID types.String `tfsdk:"file_id"` 20 | } 21 | 22 | func attributeTypes() map[string]attr.Type { 23 | return map[string]attr.Type{ 24 | "file_id": types.StringType, 25 | } 26 | } 27 | 28 | func (m *Model) exportToCustomStorageDevice() vms.CustomStorageDevice { 29 | return vms.CustomStorageDevice{ 30 | FileVolume: m.FileID.ValueString(), 31 | Media: ptr.Ptr("cdrom"), 32 | } 33 | } 34 | 35 | func (m *Model) importFromCustomStorageDevice(d vms.CustomStorageDevice) { 36 | m.FileID = types.StringValue(d.FileVolume) 37 | } 38 | -------------------------------------------------------------------------------- /proxmox/nodes/storage/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/tasks" 14 | ) 15 | 16 | // Client is an interface for accessing the Proxmox node storage API. 17 | type Client struct { 18 | api.Client 19 | 20 | StorageName string 21 | } 22 | 23 | func (c *Client) basePath() string { 24 | return c.Client.ExpandPath("storage") 25 | } 26 | 27 | // ExpandPath expands a relative path to a full node storage API path. 28 | func (c *Client) ExpandPath(path string) string { 29 | ep := fmt.Sprintf("%s/%s", c.basePath(), c.StorageName) 30 | if path != "" { 31 | ep = fmt.Sprintf("%s/%s", ep, path) 32 | } 33 | 34 | return ep 35 | } 36 | 37 | // Tasks returns a client for managing node storage tasks. 38 | func (c *Client) Tasks() *tasks.Client { 39 | return &tasks.Client{ 40 | Client: c.Client, 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_version.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_version 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | Retrieves API version details. 8 | --- 9 | 10 | # Data Source: proxmox_virtual_environment_version 11 | 12 | Retrieves API version details. 13 | 14 | ## Example Usage 15 | 16 | ```terraform 17 | data "proxmox_virtual_environment_version" "example" {} 18 | 19 | output "data_proxmox_virtual_environment_version" { 20 | value = { 21 | release = data.proxmox_virtual_environment_version.example.release 22 | repository_id = data.proxmox_virtual_environment_version.example.repository_id 23 | version = data.proxmox_virtual_environment_version.example.version 24 | } 25 | } 26 | ``` 27 | 28 | 29 | ## Schema 30 | 31 | ### Read-Only 32 | 33 | - `id` (String) Placeholder identifier attribute. 34 | - `release` (String) The current Proxmox VE point release in `x.y` format. 35 | - `repository_id` (String) The short git revision from which this version was build. 36 | - `version` (String) The full pve-manager package version of this node. 37 | -------------------------------------------------------------------------------- /examples/data-sources/proxmox_virtual_environment_sdn_zone_qinq/data-source.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_sdn_zone_qinq" "example" { 2 | id = "qinq1" 3 | } 4 | 5 | output "data_proxmox_virtual_environment_sdn_zone_qinq" { 6 | value = { 7 | id = data.proxmox_virtual_environment_sdn_zone_qinq.example.id 8 | nodes = data.proxmox_virtual_environment_sdn_zone_qinq.example.nodes 9 | bridge = data.proxmox_virtual_environment_sdn_zone_qinq.example.bridge 10 | service_vlan = data.proxmox_virtual_environment_sdn_zone_qinq.example.service_vlan 11 | service_vlan_protocol = data.proxmox_virtual_environment_sdn_zone_qinq.example.service_vlan_protocol 12 | mtu = data.proxmox_virtual_environment_sdn_zone_qinq.example.mtu 13 | dns = data.proxmox_virtual_environment_sdn_zone_qinq.example.dns 14 | dns_zone = data.proxmox_virtual_environment_sdn_zone_qinq.example.dns_zone 15 | ipam = data.proxmox_virtual_environment_sdn_zone_qinq.example.ipam 16 | reverse_dns = data.proxmox_virtual_environment_sdn_zone_qinq.example.reverse_dns 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plan.md: -------------------------------------------------------------------------------- 1 | # Planned Project Modifications 2 | 3 | ## Columns to be Added: 4 | - Backlog 5 | - Triage 6 | - Needs Info 7 | - P0 8 | - P1 9 | - Enhancements 10 | - In Progress 11 | - Review/QA 12 | - Blocked 13 | - Done 14 | 15 | ## Custom Fields to be Added: 16 | - **Priority:** (enum: P0, P1, P2, P3) 17 | - **Severity:** (enum: blocker, major, minor, cosmetic) 18 | - **Component:** (text) 19 | - **Estimate:** (number) 20 | - **Linked PR/Branch:** (url) 21 | - **Next Action:** (text) 22 | 23 | ## Labels to be Created/Updated: 24 | - **New Labels:** 25 | - priority:P0 26 | - priority:P1 27 | - priority:P2 28 | - priority:P3 29 | - type:bug 30 | - type:enhancement 31 | - lifecycle:needs-repro 32 | - lifecycle:needs-info (reuse existing "pending author's response") 33 | - lifecycle:acknowledged 34 | - status:in-progress 35 | - status:blocked 36 | - regression 37 | - docs 38 | - tests 39 | 40 | ## Automation Rules to be Created: 41 | - Label priority:* moves card to corresponding column (priority:P0 -> P0 column etc.) 42 | - Label lifecycle:needs-info -> move to Needs Info 43 | - When a PR is opened referencing an issue, move card to In Progress 44 | - When PR merged, move card to Review/QA -------------------------------------------------------------------------------- /proxmox/cluster/acme/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package acme 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/acme/account" 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/acme/plugins" 15 | ) 16 | 17 | // Client is an interface for accessing the Proxmox ACME API. 18 | type Client struct { 19 | api.Client 20 | } 21 | 22 | // ExpandPath expands a relative path to a full cluster ACME API path. 23 | func (c *Client) ExpandPath(path string) string { 24 | return fmt.Sprintf("cluster/acme/%s", path) 25 | } 26 | 27 | // Account returns a client for managing the cluster's ACME account. 28 | func (c *Client) Account() *account.Client { 29 | return &account.Client{Client: c.Client} 30 | } 31 | 32 | // Plugins returns a client for managing the cluster's ACME plugins. 33 | func (c *Client) Plugins() *plugins.Client { 34 | return &plugins.Client{Client: c.Client} 35 | } 36 | -------------------------------------------------------------------------------- /proxmox/api/client_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package api 8 | 9 | import ( 10 | "io" 11 | "os" 12 | ) 13 | 14 | // MultiPartData enables multipart uploads in DoRequest. 15 | type MultiPartData struct { 16 | Boundary string 17 | Reader io.Reader 18 | Size *int64 19 | } 20 | 21 | // ErrorResponseBody contains the body of an error response. 22 | type ErrorResponseBody struct { 23 | Data *string `json:"data"` 24 | Message *string `json:"message"` 25 | Errors *map[string]string `json:"errors"` 26 | } 27 | 28 | // FileUploadRequest is a request for uploading a file. 29 | type FileUploadRequest struct { 30 | ContentType string 31 | FileName string 32 | File *os.File 33 | // Will be handled as unsigned 32-bit integer since the underlying type of os.FileMode is the same, but must be parsed 34 | // as string due to the conversion of the octal format. 35 | // References: 36 | // 1. https://en.wikipedia.org/wiki/Chmod#Special_modes 37 | Mode string 38 | } 39 | -------------------------------------------------------------------------------- /proxmox/api/token_auth.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package api 8 | 9 | import ( 10 | "context" 11 | "net/http" 12 | "strings" 13 | ) 14 | 15 | type tokenAuthenticator struct { 16 | username string 17 | token string 18 | } 19 | 20 | // NewTokenAuthenticator creates a new authenticator that uses a PVE API Token 21 | // for authentication. 22 | func NewTokenAuthenticator(toc TokenCredentials) (Authenticator, error) { 23 | return &tokenAuthenticator{ 24 | username: strings.Split(toc.APIToken, "!")[0], 25 | token: toc.APIToken, 26 | }, nil 27 | } 28 | 29 | func (t *tokenAuthenticator) IsRoot(_ context.Context) bool { 30 | return t.username == rootUsername 31 | } 32 | 33 | func (t *tokenAuthenticator) IsRootTicket(_ context.Context) bool { 34 | // Logged using a token, therefore not a ticket login 35 | return false 36 | } 37 | 38 | func (t *tokenAuthenticator) AuthenticateRequest(_ context.Context, req *http.Request) error { 39 | req.Header.Set("Authorization", "PVEAPIToken="+t.token) 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /proxmoxtf/resource/role_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package resource 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmoxtf/test" 15 | ) 16 | 17 | // TestRoleInstantiation tests whether the Role instance can be instantiated. 18 | func TestRoleInstantiation(t *testing.T) { 19 | t.Parallel() 20 | 21 | s := Role() 22 | if s == nil { 23 | t.Fatalf("Cannot instantiate Role") 24 | } 25 | } 26 | 27 | // TestRoleSchema tests the Role schema. 28 | func TestRoleSchema(t *testing.T) { 29 | t.Parallel() 30 | 31 | s := Role().Schema 32 | 33 | test.AssertRequiredArguments(t, s, []string{ 34 | mkResourceVirtualEnvironmentRolePrivileges, 35 | mkResourceVirtualEnvironmentRoleRoleID, 36 | }) 37 | 38 | test.AssertValueTypes(t, s, map[string]schema.ValueType{ 39 | mkResourceVirtualEnvironmentRolePrivileges: schema.TypeSet, 40 | mkResourceVirtualEnvironmentRoleRoleID: schema.TypeString, 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /proxmox/version/capabilities.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package version 8 | 9 | import "github.com/hashicorp/go-version" 10 | 11 | // MinimumProxmoxVersion is the minimum supported Proxmox version by the provider. 12 | // 13 | //nolint:gochecknoglobals 14 | var MinimumProxmoxVersion = ProxmoxVersion{*version.Must(version.NewVersion("8.0.0"))} 15 | 16 | // SupportImportContentType checks if the Proxmox version supports the `import` content type when uploading disk images. 17 | // See https://bugzilla.proxmox.com/show_bug.cgi?id=2424 18 | func (v *ProxmoxVersion) SupportImportContentType() bool { 19 | return v.GreaterThanOrEqual(version.Must(version.NewVersion("8.4.0"))) 20 | } 21 | 22 | // SupportModernAptSources checks if the Proxmox version uses the modern DEB822 format (.sources) for APT repositories. 23 | // PVE 9.0 and above use the new .sources format instead of the legacy .list format. 24 | func (v *ProxmoxVersion) SupportModernAptSources() bool { 25 | return v.GreaterThanOrEqual(version.Must(version.NewVersion("9.0.0"))) 26 | } 27 | -------------------------------------------------------------------------------- /proxmoxtf/resource/validators/network.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package validators 8 | 9 | import ( 10 | "fmt" 11 | "regexp" 12 | 13 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 14 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 15 | ) 16 | 17 | // MACAddress is a schema validation function for MAC address. 18 | func MACAddress() schema.SchemaValidateDiagFunc { 19 | return validation.ToDiagFunc(func(i any, path string) ([]string, []error) { 20 | v, ok := i.(string) 21 | 22 | var ws []string 23 | 24 | var es []error 25 | 26 | if !ok { 27 | es = append(es, fmt.Errorf("expected type of %q to be string", path)) 28 | return ws, es 29 | } 30 | 31 | if v != "" { 32 | r := regexp.MustCompile(`^[A-Fa-f0-9]{2}(:[A-Fa-f0-9]{2}){5}$`) 33 | ok := r.MatchString(v) 34 | 35 | if !ok { 36 | es = append(es, fmt.Errorf("expected %q to be a valid MAC address (A0:B1:C2:D3:E4:F5), got %q", path, v)) 37 | return ws, es 38 | } 39 | } 40 | 41 | return ws, es 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /templates/guides/clone-vm.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | page_title: "Clone a VM" 4 | subcategory: Guides 5 | description: |- 6 | This guide explains how to create a VM template and clone it to a new VM. 7 | --- 8 | 9 | # Clone a VM 10 | 11 | ## Create a VM template 12 | 13 | VM templates in Proxmox provide an efficient way to create multiple identical VMs. Templates act as a base image that can be cloned to create new VMs, ensuring consistency and reducing the time needed to provision new instances. When a VM is created as a template, it is read-only and cannot be started, but can be cloned multiple times to create new VMs. 14 | 15 | You can create a template with Terraform by setting the `template` attribute to `true` when creating the VM resource: 16 | 17 | {{ codefile "terraform" "examples/guides/clone-vm/template.tf" }} 18 | 19 | Once you have a template, you can clone it to create new VMs. The cloned VMs will inherit all configuration from the template but can be customized further as needed. 20 | 21 | {{ codefile "terraform" "examples/guides/clone-vm/clone.tf" }} 22 | 23 | Full example is available in the [examples/guides/clone-vm](https://github.com/bpg/terraform-provider-proxmox/tree/main/examples/guides/clone-vm) directory. 24 | -------------------------------------------------------------------------------- /templates/resources/virtual_environment_vm2.md.tmpl: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: {{.Name}} 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | description: |- 7 | {{ .Description | plainmarkdown | trimspace | prefixlines " " }} 8 | --- 9 | 10 | # {{.Type}}: {{.Name}} 11 | 12 | !> **DO NOT USE** 13 | {{ .Description | trimspace }} 14 | 15 | -> Many attributes are marked as **optional** _and_ **computed** in the schema, 16 | hence you may seem added to the plan with "(known after apply)" status, even if they are not set in the configuration. 17 | This is done to support the `clone` operation, when a VM is created from an existing VM or template, 18 | and the source attributes are copied to the clone.

19 | Computed attributes allow the provider to set those attributes without user input. 20 | The attributes are also marked as optional to allow the practitioner to set (or overwrite) them if needed. 21 | 22 | {{ if .HasExample -}} 23 | ## Example Usage 24 | 25 | {{ codefile "terraform" .ExampleFile }} 26 | {{- end }} 27 | 28 | {{ .SchemaMarkdown | trimspace }} 29 | {{- if .HasImport }} 30 | 31 | ## Import 32 | 33 | Import is supported using the following syntax: 34 | 35 | {{ codefile "shell" .ImportFile }} 36 | {{- end }} 37 | -------------------------------------------------------------------------------- /utils/env.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package utils 8 | 9 | import ( 10 | "os" 11 | "strconv" 12 | ) 13 | 14 | // GetAnyStringEnv returns the first non-empty string value from the environment variables. 15 | func GetAnyStringEnv(ks ...string) string { 16 | for _, k := range ks { 17 | if v := os.Getenv(k); v != "" { 18 | return v 19 | } 20 | } 21 | 22 | return "" 23 | } 24 | 25 | // GetAnyBoolEnv returns the first non-empty boolean value from the environment variables. 26 | func GetAnyBoolEnv(ks ...string) bool { 27 | val := "" 28 | 29 | for _, k := range ks { 30 | if v := os.Getenv(k); v != "" { 31 | val = v 32 | break 33 | } 34 | } 35 | 36 | return val == "true" || val == "1" 37 | } 38 | 39 | // GetAnyIntEnv returns the first non-empty integer value from the environment variables. 40 | func GetAnyIntEnv(ks ...string) int { 41 | for _, k := range ks { 42 | if v := os.Getenv(k); v != "" { 43 | if i, err := strconv.Atoi(v); err == nil { 44 | return i 45 | } 46 | } 47 | } 48 | 49 | return 0 50 | } 51 | -------------------------------------------------------------------------------- /fwprovider/cluster/ha/validators.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package ha 8 | 9 | import ( 10 | "github.com/hashicorp/terraform-plugin-framework/schema/validator" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/fwprovider/validators" 13 | "github.com/bpg/terraform-provider-proxmox/proxmox/types" 14 | ) 15 | 16 | // resourceIDValidator returns a new HA resource identifier validator. 17 | func resourceIDValidator() validator.String { 18 | return validators.NewParseValidator(types.ParseHAResourceID, "value must be a valid HA resource identifier") 19 | } 20 | 21 | // resourceStateValidator returns a new HA resource state validator. 22 | func resourceStateValidator() validator.String { 23 | return validators.NewParseValidator(types.ParseHAResourceState, "value must be a valid HA resource state") 24 | } 25 | 26 | // resourceTypeValidator returns a new HA resource type validator. 27 | func resourceTypeValidator() validator.String { 28 | return validators.NewParseValidator(types.ParseHAResourceType, "value must be a valid HA resource type") 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: ':bug: bug' 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Create a resource '....' 16 | 2. Run '....' 17 | 3. See error 18 | 4. Modify the resource '....' 19 | 5. Run '....' 20 | 6. See error 21 | 22 | Please also provide a minimal Terraform configuration that reproduces the issue. 23 | 24 | ```hcl 25 | 26 | # >>> put your example here <<< # 27 | 28 | ``` 29 | 30 | and the output of `terraform|tofu apply`. 31 | ```text 32 | 33 | ``` 34 | 35 | 36 | **Expected behavior** 37 | A clear and concise description of what you expected to happen. 38 | 39 | **Screenshots** 40 | If applicable, add screenshots to help explain your problem. 41 | 42 | **Additional context** 43 | Add any other context about the problem here. 44 | 45 | - Single or clustered Proxmox: 46 | - Proxmox version: 47 | - Provider version (ideally it should be the latest version): 48 | - Terraform/OpenTofu version: 49 | - OS (where you run Terraform/OpenTofu from): 50 | - Debug logs (`TF_LOG=DEBUG terraform apply`): 51 | -------------------------------------------------------------------------------- /proxmox/nodes/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package nodes 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 15 | ) 16 | 17 | // GetConfig retrieves the config for a node. 18 | func (c *Client) GetConfig(ctx context.Context) (*[]ConfigGetResponseData, error) { 19 | resBody := &ConfigGetResponseBody{} 20 | 21 | err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("config"), nil, resBody) 22 | if err != nil { 23 | return nil, fmt.Errorf("error retrieving node config: %w", err) 24 | } 25 | 26 | if resBody.Data == nil { 27 | return nil, api.ErrNoDataObjectInResponse 28 | } 29 | 30 | return resBody.Data, nil 31 | } 32 | 33 | // UpdateConfig updates the config for a node. 34 | func (c *Client) UpdateConfig(ctx context.Context, d *ConfigUpdateRequestBody) error { 35 | err := c.DoRequest(ctx, http.MethodPost, c.ExpandPath("config"), d, nil) 36 | if err != nil { 37 | return fmt.Errorf("error updating node config: %w", err) 38 | } 39 | 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /proxmox/nodes/dns.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package nodes 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 15 | ) 16 | 17 | // GetDNS retrieves the DNS configuration for a node. 18 | func (c *Client) GetDNS(ctx context.Context) (*DNSGetResponseData, error) { 19 | resBody := &DNSGetResponseBody{} 20 | 21 | err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("dns"), nil, resBody) 22 | if err != nil { 23 | return nil, fmt.Errorf("error retrieving DNS configuration: %w", err) 24 | } 25 | 26 | if resBody.Data == nil { 27 | return nil, api.ErrNoDataObjectInResponse 28 | } 29 | 30 | return resBody.Data, nil 31 | } 32 | 33 | // UpdateDNS updates the DNS configuration for a node. 34 | func (c *Client) UpdateDNS(ctx context.Context, d *DNSUpdateRequestBody) error { 35 | err := c.DoRequest(ctx, http.MethodPut, c.ExpandPath("dns"), d, nil) 36 | if err != nil { 37 | return fmt.Errorf("error updating DNS configuration: %w", err) 38 | } 39 | 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /proxmox/cluster/ha/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package ha 8 | 9 | import ( 10 | "fmt" 11 | 12 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 13 | hagroups "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/ha/groups" 14 | haresources "github.com/bpg/terraform-provider-proxmox/proxmox/cluster/ha/resources" 15 | ) 16 | 17 | // Client is an interface for accessing the Proxmox High Availability API. 18 | type Client struct { 19 | api.Client 20 | } 21 | 22 | // ExpandPath expands a relative path to a full cluster API path. 23 | func (c *Client) ExpandPath(path string) string { 24 | return fmt.Sprintf("cluster/ha/%s", path) 25 | } 26 | 27 | // Groups returns a client for managing the cluster's High Availability groups. 28 | func (c *Client) Groups() *hagroups.Client { 29 | return &hagroups.Client{Client: c.Client} 30 | } 31 | 32 | // Resources returns a client for managing the cluster's High Availability resources. 33 | func (c *Client) Resources() *haresources.Client { 34 | return &haresources.Client{Client: c.Client} 35 | } 36 | -------------------------------------------------------------------------------- /proxmox/nodes/dns_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package nodes 8 | 9 | // DNSGetResponseBody contains the body from a DNS get response. 10 | type DNSGetResponseBody struct { 11 | Data *DNSGetResponseData `json:"data,omitempty"` 12 | } 13 | 14 | // DNSGetResponseData contains the data from a DNS get response. 15 | type DNSGetResponseData struct { 16 | Server1 *string `json:"dns1,omitempty" url:"dns1,omitempty"` 17 | Server2 *string `json:"dns2,omitempty" url:"dns2,omitempty"` 18 | Server3 *string `json:"dns3,omitempty" url:"dns3,omitempty"` 19 | SearchDomain *string `json:"search,omitempty" url:"search,omitempty"` 20 | } 21 | 22 | // DNSUpdateRequestBody contains the body for a DNS update request. 23 | type DNSUpdateRequestBody struct { 24 | Server1 *string `json:"dns1,omitempty" url:"dns1,omitempty"` 25 | Server2 *string `json:"dns2,omitempty" url:"dns2,omitempty"` 26 | Server3 *string `json:"dns3,omitempty" url:"dns3,omitempty"` 27 | SearchDomain *string `json:"search,omitempty" url:"search,omitempty"` 28 | } 29 | -------------------------------------------------------------------------------- /proxmoxtf/datasource/groups_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package datasource 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmoxtf/test" 15 | ) 16 | 17 | // TestGroupsInstantiation tests whether the Groups instance can be instantiated. 18 | func TestGroupsInstantiation(t *testing.T) { 19 | t.Parallel() 20 | 21 | s := Groups() 22 | if s == nil { 23 | t.Fatalf("Cannot instantiate Groups") 24 | } 25 | } 26 | 27 | // TestGroupsSchema tests the Groups schema. 28 | func TestGroupsSchema(t *testing.T) { 29 | t.Parallel() 30 | 31 | s := Groups().Schema 32 | 33 | test.AssertComputedAttributes(t, s, []string{ 34 | mkDataSourceVirtualEnvironmentGroupsComments, 35 | mkDataSourceVirtualEnvironmentGroupsGroupIDs, 36 | }) 37 | 38 | test.AssertValueTypes(t, s, map[string]schema.ValueType{ 39 | mkDataSourceVirtualEnvironmentGroupsComments: schema.TypeList, 40 | mkDataSourceVirtualEnvironmentGroupsGroupIDs: schema.TypeList, 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /examples/guides/clone-vm/clone.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_vm" "ubuntu_clone" { 2 | name = "ubuntu-clone" 3 | node_name = var.virtual_environment_node_name 4 | 5 | clone { 6 | vm_id = proxmox_virtual_environment_vm.ubuntu_template.id 7 | } 8 | 9 | agent { 10 | # NOTE: The agent is installed and enabled as part of the cloud-init configuration in the template VM, see cloud-config.tf 11 | # The working agent is *required* to retrieve the VM IP addresses. 12 | # If you are using a different cloud-init configuration, or a different clone source 13 | # that does not have the qemu-guest-agent installed, you may need to disable the `agent` below and remove the `vm_ipv4_address` output. 14 | # See https://registry.terraform.io/providers/bpg/proxmox/latest/docs/resources/virtual_environment_vm#qemu-guest-agent for more details. 15 | enabled = true 16 | } 17 | 18 | memory { 19 | dedicated = 768 20 | } 21 | 22 | initialization { 23 | dns { 24 | servers = ["1.1.1.1"] 25 | } 26 | ip_config { 27 | ipv4 { 28 | address = "dhcp" 29 | } 30 | } 31 | } 32 | } 33 | 34 | output "vm_ipv4_address" { 35 | value = proxmox_virtual_environment_vm.ubuntu_clone.ipv4_addresses[1][0] 36 | } 37 | -------------------------------------------------------------------------------- /proxmox/cluster/options.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package cluster 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 15 | ) 16 | 17 | // GetOptions retrieves the cluster options. 18 | func (c *Client) GetOptions(ctx context.Context) (*OptionsResponseData, error) { 19 | resBody := &OptionsResponseBody{} 20 | 21 | err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("options"), nil, resBody) 22 | if err != nil { 23 | return nil, fmt.Errorf("error reading Cluster options: %w", err) 24 | } 25 | 26 | if resBody.Data == nil { 27 | return nil, api.ErrNoDataObjectInResponse 28 | } 29 | 30 | return resBody.Data, nil 31 | } 32 | 33 | // CreateUpdateOptions updates the cluster options. 34 | func (c *Client) CreateUpdateOptions(ctx context.Context, data *OptionsRequestData) error { 35 | err := c.DoRequest(ctx, http.MethodPut, c.ExpandPath("options"), data, nil) 36 | if err != nil { 37 | return fmt.Errorf("error updating Cluster resource: %w", err) 38 | } 39 | 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /proxmox/nodes/hosts.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package nodes 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 15 | ) 16 | 17 | // GetHosts retrieves the Hosts configuration for a node. 18 | func (c *Client) GetHosts(ctx context.Context) (*HostsGetResponseData, error) { 19 | resBody := &HostsGetResponseBody{} 20 | 21 | err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("hosts"), nil, resBody) 22 | if err != nil { 23 | return nil, fmt.Errorf("error retrieving hosts configuration: %w", err) 24 | } 25 | 26 | if resBody.Data == nil { 27 | return nil, api.ErrNoDataObjectInResponse 28 | } 29 | 30 | return resBody.Data, nil 31 | } 32 | 33 | // UpdateHosts updates the Hosts configuration for a node. 34 | func (c *Client) UpdateHosts(ctx context.Context, d *HostsUpdateRequestBody) error { 35 | err := c.DoRequest(ctx, http.MethodPost, c.ExpandPath("hosts"), d, nil) 36 | if err != nil { 37 | return fmt.Errorf("error updating hosts configuration: %w", err) 38 | } 39 | 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /proxmox/nodes/query_url_metadata_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package nodes 8 | 9 | import "github.com/bpg/terraform-provider-proxmox/proxmox/types" 10 | 11 | // QueryURLMetadataGetResponseBody contains the body from a QueryURLMetadata get response. 12 | type QueryURLMetadataGetResponseBody struct { 13 | Data *QueryURLMetadataGetResponseData `json:"data,omitempty"` 14 | } 15 | 16 | // QueryURLMetadataGetResponseData contains the data from a QueryURLMetadata get response. 17 | type QueryURLMetadataGetResponseData struct { 18 | Filename *string `json:"filename,omitempty" url:"filename,omitempty"` 19 | Mimetype *string `json:"mimetype,omitempty" url:"mimetype,omitempty"` 20 | Size *int64 `json:"size,omitempty" url:"size,omitempty"` 21 | } 22 | 23 | // QueryURLMetadataGetRequestBody contains the body for a QueryURLMetadata get request. 24 | type QueryURLMetadataGetRequestBody struct { 25 | Verify *types.CustomBool `json:"verify-certificates,omitempty" url:"verify-certificates,omitempty,int"` 26 | URL string `json:"url" url:"url"` 27 | } 28 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_acme_plugin.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_acme_plugin 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | Retrieves a single ACME plugin by plugin ID name. 8 | --- 9 | 10 | # Data Source: proxmox_virtual_environment_acme_plugin 11 | 12 | Retrieves a single ACME plugin by plugin ID name. 13 | 14 | ## Example Usage 15 | 16 | ```terraform 17 | data "proxmox_virtual_environment_acme_plugin" "example" { 18 | plugin = "standalone" 19 | } 20 | 21 | output "data_proxmox_virtual_environment_acme_plugin" { 22 | value = data.proxmox_virtual_environment_acme_plugin.example 23 | } 24 | ``` 25 | 26 | 27 | ## Schema 28 | 29 | ### Required 30 | 31 | - `plugin` (String) ACME Plugin ID name. 32 | 33 | ### Read-Only 34 | 35 | - `api` (String) API plugin name. 36 | - `data` (Map of String) DNS plugin data. 37 | - `digest` (String) Prevent changes if current configuration file has a different digest. This can be used to prevent concurrent modifications. 38 | - `type` (String) ACME challenge type (dns, standalone). 39 | - `validation_delay` (Number) Extra delay in seconds to wait before requesting validation. Allows to cope with a long TTL of DNS records (0 - 172800). 40 | -------------------------------------------------------------------------------- /proxmox/version/version_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package version 8 | 9 | import ( 10 | "fmt" 11 | "strings" 12 | 13 | "github.com/hashicorp/go-version" 14 | ) 15 | 16 | // ResponseBody contains the body from a version response. 17 | type ResponseBody struct { 18 | Data *ResponseData `json:"data,omitempty"` 19 | } 20 | 21 | // ResponseData contains the data from a version response. 22 | type ResponseData struct { 23 | Console string `json:"console"` 24 | Release string `json:"release"` 25 | RepositoryID string `json:"repoid"` 26 | Version ProxmoxVersion `json:"version"` 27 | } 28 | 29 | type ProxmoxVersion struct { 30 | version.Version 31 | } 32 | 33 | func (v *ProxmoxVersion) UnmarshalJSON(data []byte) error { 34 | // Unmarshal the version string into a go-version Version object, remove wrapping quotes if any 35 | ver, err := version.NewVersion(strings.Trim(string(data), "\"")) 36 | if err != nil { 37 | return fmt.Errorf("failed to parse version %q: %w", string(data), err) 38 | } 39 | 40 | v.Version = *ver 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /proxmoxtf/datasource/role_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package datasource 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmoxtf/test" 15 | ) 16 | 17 | // TestRoleInstantiation tests whether the Role instance can be instantiated. 18 | func TestRoleInstantiation(t *testing.T) { 19 | t.Parallel() 20 | 21 | s := Role() 22 | if s == nil { 23 | t.Fatalf("Cannot instantiate Role") 24 | } 25 | } 26 | 27 | // TestRoleSchema tests the Role schema. 28 | func TestRoleSchema(t *testing.T) { 29 | t.Parallel() 30 | 31 | s := Role().Schema 32 | 33 | test.AssertRequiredArguments(t, s, []string{ 34 | mkDataSourceVirtualEnvironmentRoleID, 35 | }) 36 | 37 | test.AssertComputedAttributes(t, s, []string{ 38 | mkDataSourceVirtualEnvironmentRolePrivileges, 39 | }) 40 | 41 | test.AssertValueTypes(t, s, map[string]schema.ValueType{ 42 | mkDataSourceVirtualEnvironmentRoleID: schema.TypeString, 43 | mkDataSourceVirtualEnvironmentRolePrivileges: schema.TypeSet, 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /proxmoxtf/resource/firewall/alias_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package firewall 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 13 | "github.com/stretchr/testify/require" 14 | 15 | "github.com/bpg/terraform-provider-proxmox/proxmoxtf/test" 16 | ) 17 | 18 | // TestAliasInstantiation tests whether the Alias instance can be instantiated. 19 | func TestAliasInstantiation(t *testing.T) { 20 | t.Parallel() 21 | require.NotNilf(t, Alias(), "Cannot instantiate Alias") 22 | } 23 | 24 | // TestAliasSchema tests the Alias Schema. 25 | func TestAliasSchema(t *testing.T) { 26 | t.Parallel() 27 | 28 | s := Alias().Schema 29 | 30 | test.AssertRequiredArguments(t, s, []string{ 31 | mkAliasName, 32 | mkAliasCIDR, 33 | }) 34 | 35 | test.AssertOptionalArguments(t, s, []string{ 36 | mkSelectorVMID, 37 | mkSelectorNodeName, 38 | mkAliasComment, 39 | }) 40 | 41 | test.AssertValueTypes(t, s, map[string]schema.ValueType{ 42 | mkAliasName: schema.TypeString, 43 | mkAliasCIDR: schema.TypeString, 44 | mkAliasComment: schema.TypeString, 45 | }) 46 | } 47 | -------------------------------------------------------------------------------- /fwprovider/validators/strings.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package validators 8 | 9 | import ( 10 | "fmt" 11 | "regexp" 12 | "strings" 13 | 14 | "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" 15 | "github.com/hashicorp/terraform-plugin-framework/schema/validator" 16 | ) 17 | 18 | // AbsoluteFilePathValidator validates that a string is an absolute file path. 19 | func AbsoluteFilePathValidator() validator.String { 20 | return NewParseValidator( 21 | func(s string) (string, error) { 22 | if strings.HasPrefix(s, "/") { 23 | return s, nil 24 | } 25 | 26 | return s, fmt.Errorf("%q is not an absolute path", s) 27 | }, 28 | "must be an absolute file path", 29 | ) 30 | } 31 | 32 | // NonEmptyString returns a new validator to ensure a non-empty string. 33 | func NonEmptyString() validator.String { 34 | return stringvalidator.All( 35 | stringvalidator.UTF8LengthAtLeast(1), 36 | stringvalidator.RegexMatches(regexp.MustCompile(`^\S|^$`), "must not start with whitespace"), 37 | stringvalidator.RegexMatches(regexp.MustCompile(`\S$|^$`), "must not end with whitespace"), 38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_sdn_vnets.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_sdn_vnets 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | Retrieves information about all SDN VNets in Proxmox. This data source lists all virtual networks configured in the Software-Defined Networking setup. 8 | --- 9 | 10 | # Data Source: proxmox_virtual_environment_sdn_vnets 11 | 12 | Retrieves information about all SDN VNets in Proxmox. This data source lists all virtual networks configured in the Software-Defined Networking setup. 13 | 14 | ## Example Usage 15 | 16 | ```terraform 17 | # List all SDN VNets 18 | data "proxmox_virtual_environment_sdn_vnets" "all" {} 19 | 20 | output "data_proxmox_virtual_environment_sdn_vnets_all" { 21 | value = { 22 | vnets = data.proxmox_virtual_environment_sdn_vnets.all.vnets 23 | } 24 | } 25 | ``` 26 | 27 | 28 | ## Schema 29 | 30 | ### Read-Only 31 | 32 | - `vnets` (List of Object) List of SDN VNets. (see [below for nested schema](#nestedatt--vnets)) 33 | 34 | 35 | ### Nested Schema for `vnets` 36 | 37 | Read-Only: 38 | 39 | - `alias` (String) 40 | - `id` (String) 41 | - `isolate_ports` (Boolean) 42 | - `tag` (Number) 43 | - `vlan_aware` (Boolean) 44 | - `zone` (String) 45 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_sdn_subnet.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_sdn_subnet 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | Retrieve details about a specific SDN Subnet in Proxmox VE. 8 | --- 9 | 10 | # Data Source: proxmox_virtual_environment_sdn_subnet 11 | 12 | Retrieve details about a specific SDN Subnet in Proxmox VE. 13 | 14 | 15 | 16 | 17 | ## Schema 18 | 19 | ### Required 20 | 21 | - `cidr` (String) A CIDR network address, for example 10.0.0.0/8 22 | - `vnet` (String) The VNet this subnet belongs to. 23 | 24 | ### Optional 25 | 26 | - `dhcp_range` (Attributes) DHCP range (start and end IPs). (see [below for nested schema](#nestedatt--dhcp_range)) 27 | 28 | ### Read-Only 29 | 30 | - `dhcp_dns_server` (String) The DNS server used for DHCP. 31 | - `dns_zone_prefix` (String) Prefix used for DNS zone delegation. 32 | - `gateway` (String) The gateway address for the subnet. 33 | - `id` (String) The full ID in the format 'vnet-id/subnet-id'. 34 | - `snat` (Boolean) Whether SNAT is enabled for the subnet. 35 | 36 | 37 | ### Nested Schema for `dhcp_range` 38 | 39 | Read-Only: 40 | 41 | - `end_address` (String) End of the DHCP range. 42 | - `start_address` (String) Start of the DHCP range. 43 | -------------------------------------------------------------------------------- /proxmoxtf/datasource/roles_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package datasource 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmoxtf/test" 15 | ) 16 | 17 | // TestRolesInstantiation tests whether the Roles instance can be instantiated. 18 | func TestRolesInstantiation(t *testing.T) { 19 | t.Parallel() 20 | 21 | s := Roles() 22 | if s == nil { 23 | t.Fatalf("Cannot instantiate Roles") 24 | } 25 | } 26 | 27 | // TestRolesSchema tests the Roles schema. 28 | func TestRolesSchema(t *testing.T) { 29 | t.Parallel() 30 | 31 | s := Roles().Schema 32 | 33 | test.AssertComputedAttributes(t, s, []string{ 34 | mkDataSourceVirtualEnvironmentRolesPrivileges, 35 | mkDataSourceVirtualEnvironmentRolesRoleIDs, 36 | mkDataSourceVirtualEnvironmentRolesSpecial, 37 | }) 38 | 39 | test.AssertValueTypes(t, s, map[string]schema.ValueType{ 40 | mkDataSourceVirtualEnvironmentRolesPrivileges: schema.TypeList, 41 | mkDataSourceVirtualEnvironmentRolesRoleIDs: schema.TypeList, 42 | mkDataSourceVirtualEnvironmentRolesSpecial: schema.TypeList, 43 | }) 44 | } 45 | -------------------------------------------------------------------------------- /docs/resources/virtual_environment_dns.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_dns 4 | parent: Resources 5 | subcategory: Virtual Environment 6 | --- 7 | 8 | # Resource: proxmox_virtual_environment_dns 9 | 10 | Manages the DNS configuration for a specific node. 11 | 12 | ## Example Usage 13 | 14 | ```hcl 15 | resource "proxmox_virtual_environment_dns" "first_node_dns_configuration" { 16 | domain = data.proxmox_virtual_environment_dns.first_node_dns_configuration.domain 17 | node_name = data.proxmox_virtual_environment_dns.first_node_dns_configuration.node_name 18 | 19 | servers = [ 20 | "1.1.1.1", 21 | "1.0.0.1", 22 | ] 23 | } 24 | 25 | data "proxmox_virtual_environment_dns" "first_node_dns_configuration" { 26 | node_name = "first-node" 27 | } 28 | ``` 29 | 30 | ## Argument Reference 31 | 32 | - `domain` - (Required) The DNS search domain. 33 | - `node_name` - (Required) A node name. 34 | - `servers` - (Optional) The DNS servers. 35 | 36 | ## Attribute Reference 37 | 38 | There are no additional attributes available for this resource. 39 | 40 | ## Important Notes 41 | 42 | Be careful not to use this resource multiple times for the same node. 43 | 44 | ## Import 45 | 46 | Instances can be imported using the `node_name`, e.g., 47 | 48 | ```bash 49 | terraform import proxmox_virtual_environment_dns.first_node first-node 50 | ``` 51 | -------------------------------------------------------------------------------- /proxmox/nodes/tasks/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package tasks 8 | 9 | import ( 10 | "fmt" 11 | "net/url" 12 | 13 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 14 | ) 15 | 16 | // Client is an interface for performing requests against the Proxmox 'tasks' API. 17 | type Client struct { 18 | api.Client 19 | } 20 | 21 | // ExpandPath expands a path relative to the client's base path. 22 | func (c *Client) ExpandPath(_ string) string { 23 | panic("ExpandPath of tasks.Client must not be used. Use BuildPath instead.") 24 | } 25 | 26 | func (c *Client) baseTaskPath(taskID string) (string, error) { 27 | tid, err := ParseTaskID(taskID) 28 | if err != nil { 29 | return "", err 30 | } 31 | 32 | return fmt.Sprintf("nodes/%s/tasks/%s", 33 | url.PathEscape(tid.NodeName), 34 | url.PathEscape(taskID), 35 | ), nil 36 | } 37 | 38 | // BuildPath builds a path using information from Task ID. 39 | func (c *Client) BuildPath(taskID string, path string) (string, error) { 40 | basePath, err := c.baseTaskPath(taskID) 41 | if err != nil { 42 | return "", err 43 | } 44 | 45 | return fmt.Sprintf("%s/%s", 46 | basePath, url.PathEscape(path), 47 | ), nil 48 | } 49 | -------------------------------------------------------------------------------- /proxmox/nodes/storage/status_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | import ( 10 | "github.com/bpg/terraform-provider-proxmox/proxmox/types" 11 | ) 12 | 13 | // DatastoreGetStatusResponseBody contains the body from a datastore status get request. 14 | type DatastoreGetStatusResponseBody struct { 15 | Data *DatastoreGetStatusResponseData `json:"data,omitempty"` 16 | } 17 | 18 | // DatastoreGetStatusResponseData contains the data from a datastore status get request. 19 | type DatastoreGetStatusResponseData struct { 20 | Active *types.CustomBool `json:"active,omitempty"` 21 | AvailableBytes *int64 `json:"avail,omitempty"` 22 | Content *types.CustomCommaSeparatedList `json:"content,omitempty" url:"content,omitempty,comma"` 23 | Enabled *types.CustomBool `json:"enabled,omitempty"` 24 | Shared *types.CustomBool `json:"shared,omitempty"` 25 | TotalBytes *int64 `json:"total,omitempty"` 26 | Type *string `json:"type,omitempty"` 27 | UsedBytes *int64 `json:"used,omitempty"` 28 | } 29 | -------------------------------------------------------------------------------- /proxmoxtf/resource/dns_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package resource 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmoxtf/test" 15 | ) 16 | 17 | // TestDNSInstantiation tests whether the DNS instance can be instantiated. 18 | func TestDNSInstantiation(t *testing.T) { 19 | t.Parallel() 20 | 21 | s := DNS() 22 | if s == nil { 23 | t.Fatalf("Cannot instantiate DNS") 24 | } 25 | } 26 | 27 | // TestDNSSchema tests the DNS schema. 28 | func TestDNSSchema(t *testing.T) { 29 | t.Parallel() 30 | 31 | s := DNS().Schema 32 | 33 | test.AssertRequiredArguments(t, s, []string{ 34 | mkResourceVirtualEnvironmentDNSDomain, 35 | mkResourceVirtualEnvironmentDNSNodeName, 36 | }) 37 | 38 | test.AssertOptionalArguments(t, s, []string{ 39 | mkResourceVirtualEnvironmentDNSServers, 40 | }) 41 | 42 | test.AssertValueTypes(t, s, map[string]schema.ValueType{ 43 | mkResourceVirtualEnvironmentDNSDomain: schema.TypeString, 44 | mkResourceVirtualEnvironmentDNSNodeName: schema.TypeString, 45 | mkResourceVirtualEnvironmentDNSServers: schema.TypeList, 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /.devcontainer/post-attach.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Display welcome banner 4 | echo -e "\033[1;36m" 5 | echo "════════════════════════════════════════════════════════════════════════════════════════════" 6 | echo 7 | echo " 🚀 Terraform Provider For Proxmox Development Environment" 8 | echo 9 | echo " ⚠️ EXPERIMENTAL" 10 | echo " Use at your own risk! Some tools may be missing or not work as expected." 11 | echo 12 | echo " • Go Version: $(go version | cut -d' ' -f3 | sed 's/^go//')" 13 | echo " • Terraform Version: $(terraform version -json | jq -r '.terraform_version')" 14 | echo " • OpenTofu Version: $(tofu version -json | jq -r '.terraform_version')" 15 | echo " • Working Directory: $(pwd)" 16 | echo 17 | echo "════════════════════════════════════════════════════════════════════════════════════════════" 18 | echo -e "\033[0m" 19 | 20 | # Workaround for https://github.com/orgs/community/discussions/75161 21 | unset GIT_COMMITTER_NAME 22 | unset GIT_COMMITTER_EMAIL 23 | 24 | cat < ~/.terraformrc 25 | provider_installation { 26 | 27 | dev_overrides { 28 | "bpg/proxmox" = "${GOPATH}/bin/" 29 | } 30 | 31 | # For all other providers, install them directly from their origin provider 32 | # registries as normal. If you omit this, Terraform will _only_ use 33 | # the dev_overrides block, and so no other providers will be available. 34 | direct {} 35 | } 36 | EOF 37 | -------------------------------------------------------------------------------- /proxmox/nodes/storage/download_url.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package storage 8 | 9 | import ( 10 | "context" 11 | "fmt" 12 | "net/http" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmox/api" 15 | ) 16 | 17 | // DownloadFileByURL downloads the file using URL. 18 | func (c *Client) DownloadFileByURL( 19 | ctx context.Context, 20 | d *DownloadURLPostRequestBody, 21 | ) error { 22 | resBody := &DownloadURLResponseBody{} 23 | 24 | err := c.DoRequest(ctx, http.MethodPost, c.ExpandPath("download-url"), d, resBody) 25 | if err != nil { 26 | return fmt.Errorf("error download file by URL: %w", err) 27 | } 28 | 29 | if resBody.TaskID == nil { 30 | return api.ErrNoDataObjectInResponse 31 | } 32 | 33 | taskErr := c.Tasks().WaitForTask(ctx, *resBody.TaskID) 34 | if taskErr != nil { 35 | err = fmt.Errorf( 36 | "error download file to datastore %s: failed waiting for url download: %w", 37 | c.StorageName, 38 | taskErr, 39 | ) 40 | 41 | deleteErr := c.Tasks().DeleteTask(context.WithoutCancel(ctx), *resBody.TaskID) 42 | if deleteErr != nil { 43 | return fmt.Errorf("%w \n %w", err, deleteErr) 44 | } 45 | 46 | return err 47 | } 48 | 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /examples/guides/clone-vm/template.tf: -------------------------------------------------------------------------------- 1 | resource "proxmox_virtual_environment_vm" "ubuntu_template" { 2 | name = "ubuntu-template" 3 | node_name = var.virtual_environment_node_name 4 | 5 | template = true 6 | started = false 7 | 8 | machine = "q35" 9 | bios = "ovmf" 10 | description = "Managed by Terraform" 11 | 12 | cpu { 13 | cores = 2 14 | } 15 | 16 | memory { 17 | dedicated = 2048 18 | } 19 | 20 | efi_disk { 21 | datastore_id = var.datastore_id 22 | type = "4m" 23 | } 24 | 25 | disk { 26 | datastore_id = var.datastore_id 27 | file_id = proxmox_virtual_environment_download_file.ubuntu_cloud_image.id 28 | interface = "virtio0" 29 | iothread = true 30 | discard = "on" 31 | size = 20 32 | } 33 | 34 | initialization { 35 | ip_config { 36 | ipv4 { 37 | address = "dhcp" 38 | } 39 | } 40 | 41 | user_data_file_id = proxmox_virtual_environment_file.user_data_cloud_config.id 42 | } 43 | 44 | network_device { 45 | bridge = "vmbr0" 46 | } 47 | 48 | } 49 | 50 | resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" { 51 | content_type = "iso" 52 | datastore_id = "local" 53 | node_name = var.virtual_environment_node_name 54 | 55 | url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" 56 | } 57 | -------------------------------------------------------------------------------- /fwprovider/test/datasource_node_test.go: -------------------------------------------------------------------------------- 1 | //go:build acceptance || all 2 | 3 | /* 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | 9 | package test 10 | 11 | import ( 12 | "testing" 13 | 14 | "github.com/hashicorp/terraform-plugin-testing/helper/resource" 15 | ) 16 | 17 | func TestAccDatasourceNode(t *testing.T) { 18 | t.Parallel() 19 | 20 | te := InitEnvironment(t) 21 | 22 | tests := []struct { 23 | name string 24 | steps []resource.TestStep 25 | }{ 26 | {"read node attributes", []resource.TestStep{{ 27 | Config: te.RenderConfig(`data "proxmox_virtual_environment_node" "test" { node_name = "{{.NodeName}}" }`), 28 | Check: resource.ComposeTestCheckFunc( 29 | ResourceAttributesSet("data.proxmox_virtual_environment_node.test", []string{ 30 | "cpu_count", 31 | "cpu_sockets", 32 | "cpu_model", 33 | "memory_available", 34 | "memory_used", 35 | "memory_total", 36 | "uptime", 37 | }), 38 | ), 39 | }}}, 40 | } 41 | 42 | for _, tt := range tests { 43 | t.Run(tt.name, func(t *testing.T) { 44 | resource.ParallelTest(t, resource.TestCase{ 45 | ProtoV6ProviderFactories: te.AccProviders, 46 | Steps: tt.steps, 47 | }) 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /proxmoxtf/datasource/dns_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package datasource 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" 13 | 14 | "github.com/bpg/terraform-provider-proxmox/proxmoxtf/test" 15 | ) 16 | 17 | // TestDNSInstantiation tests whether the DNS instance can be instantiated. 18 | func TestDNSInstantiation(t *testing.T) { 19 | t.Parallel() 20 | 21 | s := DNS() 22 | if s == nil { 23 | t.Fatalf("Cannot instantiate DNS") 24 | } 25 | } 26 | 27 | // TestDNSSchema tests the DNS schema. 28 | func TestDNSSchema(t *testing.T) { 29 | t.Parallel() 30 | 31 | s := DNS().Schema 32 | 33 | test.AssertRequiredArguments(t, s, []string{ 34 | mkDataSourceVirtualEnvironmentDNSNodeName, 35 | }) 36 | 37 | test.AssertComputedAttributes(t, s, []string{ 38 | mkDataSourceVirtualEnvironmentDNSDomain, 39 | mkDataSourceVirtualEnvironmentDNSServers, 40 | }) 41 | 42 | test.AssertValueTypes(t, s, map[string]schema.ValueType{ 43 | mkDataSourceVirtualEnvironmentDNSDomain: schema.TypeString, 44 | mkDataSourceVirtualEnvironmentDNSNodeName: schema.TypeString, 45 | mkDataSourceVirtualEnvironmentDNSServers: schema.TypeList, 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /fwprovider/types/ip_addr_value.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package types 8 | 9 | import ( 10 | "context" 11 | 12 | "github.com/hashicorp/terraform-plugin-framework/attr" 13 | "github.com/hashicorp/terraform-plugin-framework/types" 14 | "github.com/hashicorp/terraform-plugin-framework/types/basetypes" 15 | ) 16 | 17 | // Ensure the implementation satisfies the expected interfaces. 18 | var _ basetypes.StringValuable = IPAddrValue{} 19 | 20 | // IPAddrValue is a type that represents an IP address value. 21 | type IPAddrValue struct { 22 | basetypes.StringValue 23 | } 24 | 25 | // Equal returns true if the two values are equal. 26 | func (v IPAddrValue) Equal(o attr.Value) bool { 27 | other, ok := o.(IPAddrValue) 28 | 29 | if !ok { 30 | return false 31 | } 32 | 33 | return v.StringValue.Equal(other.StringValue) 34 | } 35 | 36 | // Type returns the type of the value. 37 | func (v IPAddrValue) Type(_ context.Context) attr.Type { 38 | return IPAddrType{} 39 | } 40 | 41 | // NewIPAddrPointerValue returns a new IPAddrValue from a string pointer. 42 | func NewIPAddrPointerValue(value *string) IPAddrValue { 43 | return IPAddrValue{ 44 | StringValue: types.StringPointerValue(value), 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /docs/data-sources/virtual_environment_hardware_mapping_dir.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: proxmox_virtual_environment_hardware_mapping_dir 4 | parent: Data Sources 5 | subcategory: Virtual Environment 6 | description: |- 7 | Retrieves a directory mapping from a Proxmox VE cluster. 8 | --- 9 | 10 | # Data Source: proxmox_virtual_environment_hardware_mapping_dir 11 | 12 | Retrieves a directory mapping from a Proxmox VE cluster. 13 | 14 | ## Example Usage 15 | 16 | ```terraform 17 | data "proxmox_virtual_environment_hardware_mapping_dir" "example" { 18 | name = "example" 19 | } 20 | 21 | output "data_proxmox_virtual_environment_hardware_mapping_dir" { 22 | value = data.proxmox_virtual_environment_hardware_mapping_dir.example 23 | } 24 | ``` 25 | 26 | 27 | ## Schema 28 | 29 | ### Required 30 | 31 | - `name` (String) The name of this directory mapping. 32 | 33 | ### Read-Only 34 | 35 | - `comment` (String) The comment of this directory mapping. 36 | - `id` (String) The unique identifier of this directory mapping data source. 37 | - `map` (Attributes Set) The actual map of devices for the directory mapping. (see [below for nested schema](#nestedatt--map)) 38 | 39 | 40 | ### Nested Schema for `map` 41 | 42 | Read-Only: 43 | 44 | - `node` (String) The node name attribute of the map. 45 | - `path` (String) The path attribute of the map. 46 | -------------------------------------------------------------------------------- /example/data_source_virtual_environment_node.tf: -------------------------------------------------------------------------------- 1 | data "proxmox_virtual_environment_node" "example" { 2 | node_name = data.proxmox_virtual_environment_nodes.example.names[0] 3 | } 4 | 5 | output "data_proxmox_virtual_environment_node_example_cpu_count" { 6 | value = data.proxmox_virtual_environment_node.example.cpu_count 7 | } 8 | 9 | output "data_proxmox_virtual_environment_node_example_cpu_sockets" { 10 | value = data.proxmox_virtual_environment_node.example.cpu_sockets 11 | } 12 | 13 | output "data_proxmox_virtual_environment_node_example_cpu_model" { 14 | value = data.proxmox_virtual_environment_node.example.cpu_model 15 | } 16 | 17 | output "data_proxmox_virtual_environment_node_example_memory_available" { 18 | value = data.proxmox_virtual_environment_node.example.memory_available 19 | } 20 | 21 | output "data_proxmox_virtual_environment_node_example_memory_used" { 22 | value = data.proxmox_virtual_environment_node.example.memory_used 23 | } 24 | 25 | output "data_proxmox_virtual_environment_node_example_memory_total" { 26 | value = data.proxmox_virtual_environment_node.example.memory_total 27 | } 28 | 29 | output "data_proxmox_virtual_environment_node_example_node_name" { 30 | value = data.proxmox_virtual_environment_node.example.node_name 31 | } 32 | 33 | output "data_proxmox_virtual_environment_node_example_uptime" { 34 | value = data.proxmox_virtual_environment_node.example.uptime 35 | } 36 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | $schema: 'https://docs.renovatebot.com/renovate-schema.json', 3 | extends: [ 4 | 'github>bpg/renovate-config', 5 | 'github>bpg/renovate-config:automerge-github-actions', 6 | ':semanticCommitTypeAll(chore)', 7 | ], 8 | postUpdateOptions: [ 9 | 'gomodTidy', 10 | 'gomodUpdateImportPaths', 11 | ], 12 | ignorePaths: [ 13 | 'howtos/**', 14 | ], 15 | rebaseWhen: 'behind-base-branch', 16 | packageRules: [ 17 | { 18 | semanticCommitScope: 'deps', 19 | matchPackageNames: [ 20 | '*', 21 | ], 22 | }, 23 | { 24 | groupName: 'github.com/hashicorp/terraform-plugin-*', 25 | matchPackageNames: [ 26 | 'github.com/hashicorp/terraform-plugin-{/,}**', 27 | ], 28 | }, 29 | { 30 | matchFileNames: [ 31 | 'examples/**', 32 | 'example/**', 33 | 'docs/**', 34 | ], 35 | semanticCommitScope: 'docs', 36 | automerge: true, 37 | automergeType: 'branch', 38 | matchUpdateTypes: [ 39 | 'minor', 40 | 'patch', 41 | ], 42 | }, 43 | { 44 | matchManagers: [ 45 | 'github-actions', 46 | ], 47 | semanticCommitScope: 'ci', 48 | }, 49 | { 50 | matchUpdateTypes: [ 51 | 'major', 52 | ], 53 | commitMessagePrefix: '{{semanticCommitType}}({{semanticCommitScope}}):', 54 | }, 55 | ], 56 | } 57 | -------------------------------------------------------------------------------- /utils/sets.go: -------------------------------------------------------------------------------- 1 | /* 2 | * This Source Code Form is subject to the terms of the Mozilla Public 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this 4 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | */ 6 | 7 | package utils 8 | 9 | import "reflect" 10 | 11 | // SetDiff compares two slices of elements and returns the elements that are in the plan but not 12 | // in the state (toCreate), the elements that are in the plan and in the state but are different (toUpdate), 13 | // and the elements that are in the state but not in the plan (toDelete). 14 | // The keyFunc is used to extract a unique key from each element to compare them. 15 | func SetDiff[T any](plan []T, state []T, keyFunc func(t T) string) ([]T, []T, []T) { 16 | var toCreate, toUpdate, toDelete []T 17 | 18 | stateMap := map[string]T{} 19 | for _, s := range state { 20 | stateMap[keyFunc(s)] = s 21 | } 22 | 23 | planMap := map[string]T{} 24 | for _, p := range plan { 25 | planMap[keyFunc(p)] = p 26 | } 27 | 28 | for _, p := range plan { 29 | s, ok := stateMap[keyFunc(p)] 30 | if !ok { 31 | toCreate = append(toCreate, p) 32 | } else if !reflect.DeepEqual(p, s) { 33 | toUpdate = append(toUpdate, p) 34 | } 35 | } 36 | 37 | for _, s := range state { 38 | _, ok := planMap[keyFunc(s)] 39 | if !ok { 40 | toDelete = append(toDelete, s) 41 | } 42 | } 43 | 44 | return toCreate, toUpdate, toDelete 45 | } 46 | --------------------------------------------------------------------------------