0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-08-22 19:38:35 +00:00

chore(vm2): cleanup cpu implementation, refactor rearrange acc tests (#1311)

* chore(vm2): cleanup `cpu` implementation, refactor rearrange acc tests

---------

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
Pavel Boldyrev 2024-05-18 23:31:50 -04:00 committed by GitHub
parent aa309fd9ea
commit 2e34c57f6c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 897 additions and 919 deletions

View File

@ -26,6 +26,7 @@ jobs:
node: pve3 node: pve3
port: 13453 port: 13453
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
timeout-minutes: 30
environment: pve-acc environment: pve-acc
steps: steps:
- name: Dump GitHub context - name: Dump GitHub context

View File

@ -23,7 +23,7 @@ issues:
- path: _types\.go - path: _types\.go
linters: linters:
- lll - lll
- path: fwprovider/tests/.*\.go - path: fwprovider/.*_test\.go
linters: linters:
- paralleltest - paralleltest
# Exclude `lll` issues for long lines with URLs. # Exclude `lll` issues for long lines with URLs.

View File

@ -95,7 +95,7 @@ test:
.PHONY: testacc .PHONY: testacc
testacc: testacc:
@# explicitly add TF_ACC=1 to trigger the acceptance tests, `testacc.env` might be missing or incomplete @# explicitly add TF_ACC=1 to trigger the acceptance tests, `testacc.env` might be missing or incomplete
@TF_ACC=1 env $$(cat testacc.env | xargs) go test --timeout=30m -count=1 -v github.com/bpg/terraform-provider-proxmox/fwprovider/tests/... @TF_ACC=1 env $$(cat testacc.env | xargs) go test --timeout=30m -count=1 -v github.com/bpg/terraform-provider-proxmox/fwprovider/...
.PHONY: lint .PHONY: lint
lint: lint:

View File

@ -78,24 +78,24 @@ resource "proxmox_virtual_environment_file" "cloud_config" {
node_name = "pve" node_name = "pve"
source_raw { source_raw {
data = <<EOF data = <<-EOF
#cloud-config #cloud-config
users: users:
- default - default
- name: ubuntu - name: ubuntu
groups: groups:
- sudo - sudo
shell: /bin/bash shell: /bin/bash
ssh_authorized_keys: ssh_authorized_keys:
- ${trimspace(data.local_file.ssh_public_key.content)} - ${trimspace(data.local_file.ssh_public_key.content)}
sudo: ALL=(ALL) NOPASSWD:ALL sudo: ALL=(ALL) NOPASSWD:ALL
runcmd: runcmd:
- apt update - apt update
- apt install -y qemu-guest-agent net-tools - apt install -y qemu-guest-agent net-tools
- timedatectl set-timezone America/Toronto - timedatectl set-timezone America/Toronto
- systemctl enable qemu-guest-agent - systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent - systemctl start qemu-guest-agent
- echo "done" > /tmp/cloud-config.done - echo "done" > /tmp/cloud-config.done
EOF EOF
file_name = "cloud-config.yaml" file_name = "cloud-config.yaml"

View File

@ -56,24 +56,24 @@ resource "proxmox_virtual_environment_file" "cloud_config" {
node_name = "pve" node_name = "pve"
source_raw { source_raw {
data = <<EOF data = <<-EOF
#cloud-config #cloud-config
chpasswd: chpasswd:
list: | list: |
ubuntu:example ubuntu:example
expire: false expire: false
hostname: example-hostname hostname: example-hostname
packages: packages:
- qemu-guest-agent - qemu-guest-agent
users: users:
- default - default
- name: ubuntu - name: ubuntu
groups: sudo groups: sudo
shell: /bin/bash shell: /bin/bash
ssh-authorized-keys: ssh-authorized-keys:
- ${trimspace(tls_private_key.example.public_key_openssh)} - ${trimspace(tls_private_key.example.public_key_openssh)}
sudo: ALL=(ALL) NOPASSWD:ALL sudo: ALL=(ALL) NOPASSWD:ALL
EOF EOF
file_name = "example.cloud-config.yaml" file_name = "example.cloud-config.yaml"
} }

View File

@ -14,12 +14,10 @@ This is an experimental implementation of a Proxmox VM resource using Plugin Fra
-> Many attributes are marked as **optional** _and_ **computed** in the schema, -> Many attributes are marked as **optional** _and_ **computed** in the schema,
hence you may seem added to the plan with "(known after apply)" status, even if they are not set in the configuration. hence you may seem added to the plan with "(known after apply)" status, even if they are not set in the configuration.
This is done to support the `clone` operation, when a VM is created from an existing one, This is done to support the `clone` operation, when a VM is created from an existing VM or template,
and attributes of the original VM are copied to the new one.<br><br> and the source attributes are copied to the clone.<br><br>
Computed attributes allow the provider to set those attributes without user input. Computed attributes allow the provider to set those attributes without user input.
The attributes are marked as optional to allow the user to set (or overwrite) them if needed. The attributes are also marked as optional to allow the practitioner to set (or overwrite) them if needed.
In order to remove the computed attribute from the plan, you can set it to an empty value (e.g. `""` for string, `[]` for collection).

View File

@ -8,21 +8,21 @@ resource "proxmox_virtual_environment_file" "user_config" {
node_name = data.proxmox_virtual_environment_datastores.example.node_name node_name = data.proxmox_virtual_environment_datastores.example.node_name
source_raw { source_raw {
data = <<EOF data = <<-EOF
#cloud-config #cloud-config
chpasswd: chpasswd:
list: | list: |
ubuntu:example ubuntu:example
expire: false expire: false
hostname: terraform-provider-proxmox-example hostname: terraform-provider-proxmox-example
users: users:
- default - default
- name: ubuntu - name: ubuntu
groups: sudo groups: sudo
shell: /bin/bash shell: /bin/bash
ssh-authorized-keys: ssh-authorized-keys:
- ${trimspace(tls_private_key.example.public_key_openssh)} - ${trimspace(tls_private_key.example.public_key_openssh)}
sudo: ALL=(ALL) NOPASSWD:ALL sudo: ALL=(ALL) NOPASSWD:ALL
EOF EOF
file_name = "terraform-provider-proxmox-example-user-config.yaml" file_name = "terraform-provider-proxmox-example-user-config.yaml"

View File

@ -8,24 +8,24 @@ resource "proxmox_virtual_environment_file" "cloud_config" {
node_name = "pve" node_name = "pve"
source_raw { source_raw {
data = <<EOF data = <<-EOF
#cloud-config #cloud-config
users: users:
- default - default
- name: ubuntu - name: ubuntu
groups: groups:
- sudo - sudo
shell: /bin/bash shell: /bin/bash
ssh_authorized_keys: ssh_authorized_keys:
- ${trimspace(data.local_file.ssh_public_key.content)} - ${trimspace(data.local_file.ssh_public_key.content)}
sudo: ALL=(ALL) NOPASSWD:ALL sudo: ALL=(ALL) NOPASSWD:ALL
runcmd: runcmd:
- apt update - apt update
- apt install -y qemu-guest-agent net-tools - apt install -y qemu-guest-agent net-tools
- timedatectl set-timezone America/Toronto - timedatectl set-timezone America/Toronto
- systemctl enable qemu-guest-agent - systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent - systemctl start qemu-guest-agent
- echo "done" > /tmp/cloud-config.done - echo "done" > /tmp/cloud-config.done
EOF EOF
file_name = "cloud-config.yaml" file_name = "cloud-config.yaml"

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package access_test
import ( import (
"context" "context"
@ -17,47 +17,50 @@ import (
"github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
"github.com/bpg/terraform-provider-proxmox/proxmox/access" "github.com/bpg/terraform-provider-proxmox/proxmox/access"
) )
func TestAccAcl_User(t *testing.T) { func TestAccAcl_User(t *testing.T) {
te := initTestEnvironment(t) t.Parallel()
te := test.InitEnvironment(t)
userID := fmt.Sprintf("%s@pve", gofakeit.Username()) userID := fmt.Sprintf("%s@pve", gofakeit.Username())
te.addTemplateVars(map[string]any{ te.AddTemplateVars(map[string]any{
"UserID": userID, "UserID": userID,
}) })
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
CheckDestroy: nil, CheckDestroy: nil,
PreCheck: func() { PreCheck: func() {
err := te.accessClient().CreateUser(context.Background(), &access.UserCreateRequestBody{ err := te.AccessClient().CreateUser(context.Background(), &access.UserCreateRequestBody{
ID: userID, ID: userID,
Password: gofakeit.Password(true, true, true, true, false, 8), Password: gofakeit.Password(true, true, true, true, false, 8),
}) })
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
err := te.accessClient().DeleteUser(context.Background(), userID) err := te.AccessClient().DeleteUser(context.Background(), userID)
require.NoError(t, err) require.NoError(t, err)
}) })
}, },
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_acl" "test" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_acl" "test" {
user_id = "{{.UserID}}" user_id = "{{.UserID}}"
path = "/" path = "/"
role_id = "NoAccess" role_id = "NoAccess"
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_acl.test", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_acl.test", map[string]string{
"path": "/", "path": "/",
"role_id": "NoAccess", "role_id": "NoAccess",
"user_id": userID, "user_id": userID,
"propagate": "true", "propagate": "true",
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_acl.test", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_acl.test", []string{
"group_id", "group_id",
"token_id", "token_id",
}), }),
@ -70,19 +73,19 @@ func TestAccAcl_User(t *testing.T) {
ImportStateVerify: true, ImportStateVerify: true,
}, },
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_acl" "test" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_acl" "test" {
user_id = "{{.UserID}}" user_id = "{{.UserID}}"
path = "/" path = "/"
role_id = "PVEPoolUser" role_id = "PVEPoolUser"
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_acl.test", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_acl.test", map[string]string{
"path": "/", "path": "/",
"role_id": "PVEPoolUser", "role_id": "PVEPoolUser",
"user_id": userID, "user_id": userID,
"propagate": "true", "propagate": "true",
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_acl.test", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_acl.test", []string{
"group_id", "group_id",
"token_id", "token_id",
}), }),
@ -95,10 +98,10 @@ func TestAccAcl_User(t *testing.T) {
func TestAccAcl_Validators(t *testing.T) { func TestAccAcl_Validators(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(t) te := test.InitEnvironment(t)
resource.UnitTest(t, resource.TestCase{ resource.UnitTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
CheckDestroy: nil, CheckDestroy: nil,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package access_test
import ( import (
"context" "context"
@ -15,16 +15,17 @@ import (
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
"github.com/bpg/terraform-provider-proxmox/proxmox/access" "github.com/bpg/terraform-provider-proxmox/proxmox/access"
) )
func TestAccResourceUser(t *testing.T) { func TestAccResourceUser(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(t) te := test.InitEnvironment(t)
userID := fmt.Sprintf("%s@pve", gofakeit.Username()) userID := fmt.Sprintf("%s@pve", gofakeit.Username())
te.addTemplateVars(map[string]any{ te.AddTemplateVars(map[string]any{
"UserID": userID, "UserID": userID,
}) })
@ -34,7 +35,7 @@ func TestAccResourceUser(t *testing.T) {
}{ }{
{"create and update user", []resource.TestStep{ {"create and update user", []resource.TestStep{
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_user" "user" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_user" "user" {
comment = "Managed by Terraform" comment = "Managed by Terraform"
email = "{{.UserID}}" email = "{{.UserID}}"
enabled = true enabled = true
@ -43,7 +44,7 @@ func TestAccResourceUser(t *testing.T) {
last_name = "Last" last_name = "Last"
user_id = "{{.UserID}}" user_id = "{{.UserID}}"
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_user.user", map[string]string{ Check: test.ResourceAttributes("proxmox_virtual_environment_user.user", map[string]string{
"comment": "Managed by Terraform", "comment": "Managed by Terraform",
"email": userID, "email": userID,
"enabled": "true", "enabled": "true",
@ -54,13 +55,13 @@ func TestAccResourceUser(t *testing.T) {
}), }),
}, },
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_user" "user" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_user" "user" {
enabled = false enabled = false
expiration_date = "2035-01-01T22:00:00Z" expiration_date = "2035-01-01T22:00:00Z"
user_id = "{{.UserID}}" user_id = "{{.UserID}}"
first_name = "First One" first_name = "First One"
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_user.user", map[string]string{ Check: test.ResourceAttributes("proxmox_virtual_environment_user.user", map[string]string{
"enabled": "false", "enabled": "false",
"expiration_date": "2035-01-01T22:00:00Z", "expiration_date": "2035-01-01T22:00:00Z",
"first_name": "First One", "first_name": "First One",
@ -78,7 +79,7 @@ func TestAccResourceUser(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })
@ -88,11 +89,11 @@ func TestAccResourceUser(t *testing.T) {
func TestAccResourceUserToken(t *testing.T) { func TestAccResourceUserToken(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(t) te := test.InitEnvironment(t)
userID := fmt.Sprintf("%s@pve", gofakeit.Username()) userID := fmt.Sprintf("%s@pve", gofakeit.Username())
tokenName := gofakeit.Word() tokenName := gofakeit.Word()
te.addTemplateVars(map[string]any{ te.AddTemplateVars(map[string]any{
"UserID": userID, "UserID": userID,
"TokenName": tokenName, "TokenName": tokenName,
}) })
@ -105,25 +106,25 @@ func TestAccResourceUserToken(t *testing.T) {
{ {
"create and update user token", "create and update user token",
func() { func() {
err := te.accessClient().CreateUser(context.Background(), &access.UserCreateRequestBody{ err := te.AccessClient().CreateUser(context.Background(), &access.UserCreateRequestBody{
ID: userID, ID: userID,
Password: gofakeit.Password(true, true, true, true, false, 8), Password: gofakeit.Password(true, true, true, true, false, 8),
}) })
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
err := te.accessClient().DeleteUser(context.Background(), userID) err := te.AccessClient().DeleteUser(context.Background(), userID)
require.NoError(t, err) require.NoError(t, err)
}) })
}, },
[]resource.TestStep{ []resource.TestStep{
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_user_token" "user_token" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_user_token" "user_token" {
comment = "Managed by Terraform" comment = "Managed by Terraform"
token_name = "{{.TokenName}}" token_name = "{{.TokenName}}"
user_id = "{{.UserID}}" user_id = "{{.UserID}}"
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_user_token.user_token", map[string]string{ Check: test.ResourceAttributes("proxmox_virtual_environment_user_token.user_token", map[string]string{
"comment": "Managed by Terraform", "comment": "Managed by Terraform",
"id": fmt.Sprintf("%s!%s", userID, tokenName), "id": fmt.Sprintf("%s!%s", userID, tokenName),
"user_id": userID, "user_id": userID,
@ -131,7 +132,7 @@ func TestAccResourceUserToken(t *testing.T) {
}), }),
}, },
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_user_token" "user_token" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_user_token" "user_token" {
comment = "Managed by Terraform 2" comment = "Managed by Terraform 2"
expiration_date = "2033-01-01T01:01:01Z" expiration_date = "2033-01-01T01:01:01Z"
privileges_separation = false privileges_separation = false
@ -139,33 +140,33 @@ func TestAccResourceUserToken(t *testing.T) {
user_id = "{{.UserID}}" user_id = "{{.UserID}}"
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_user_token.user_token", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_user_token.user_token", map[string]string{
"comment": "Managed by Terraform 2", "comment": "Managed by Terraform 2",
"expiration_date": "2033-01-01T01:01:01Z", "expiration_date": "2033-01-01T01:01:01Z",
"privileges_separation": "false", "privileges_separation": "false",
"token_name": tokenName, "token_name": tokenName,
"user_id": userID, "user_id": userID,
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_user_token.user_token", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_user_token.user_token", []string{
"value", "value",
}), }),
), ),
}, },
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_user_token" "user_token" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_user_token" "user_token" {
comment = "Managed by Terraform 2" comment = "Managed by Terraform 2"
privileges_separation = false privileges_separation = false
token_name = "{{.TokenName}}" token_name = "{{.TokenName}}"
user_id = "{{.UserID}}" user_id = "{{.UserID}}"
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_user_token.user_token", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_user_token.user_token", map[string]string{
"comment": "Managed by Terraform 2", "comment": "Managed by Terraform 2",
"privileges_separation": "false", "privileges_separation": "false",
"token_name": tokenName, "token_name": tokenName,
"user_id": userID, "user_id": userID,
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_user_token.user_token", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_user_token.user_token", []string{
"expiration_date", "expiration_date",
"value", "value",
}), }),
@ -183,7 +184,7 @@ func TestAccResourceUserToken(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
PreCheck: tt.preCheck, PreCheck: tt.preCheck,
Steps: tt.steps, Steps: tt.steps,
}) })

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package hardwaremapping_test
import ( import (
"fmt" "fmt"
@ -18,7 +18,7 @@ import (
"github.com/hashicorp/terraform-plugin-testing/statecheck" "github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath" "github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
hwm "github.com/bpg/terraform-provider-proxmox/fwprovider/hardwaremapping" "github.com/bpg/terraform-provider-proxmox/fwprovider/test"
customtypes "github.com/bpg/terraform-provider-proxmox/fwprovider/types/hardwaremapping" customtypes "github.com/bpg/terraform-provider-proxmox/fwprovider/types/hardwaremapping"
"github.com/bpg/terraform-provider-proxmox/fwprovider/validators" "github.com/bpg/terraform-provider-proxmox/fwprovider/validators"
proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types/hardwaremapping" proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types/hardwaremapping"
@ -41,7 +41,7 @@ type accTestHardwareMappingFakeData struct {
Names []string `fake:"{noun}" fakesize:"2"` Names []string `fake:"{noun}" fakesize:"2"`
} }
func testAccResourceHardwareMappingInit(t *testing.T) (*accTestHardwareMappingFakeData, *testEnvironment) { func testAccResourceHardwareMappingInit(t *testing.T) (*accTestHardwareMappingFakeData, *test.Environment) {
t.Helper() t.Helper()
// Register a new custom function to generate random Linux device IDs. // Register a new custom function to generate random Linux device IDs.
@ -81,7 +81,7 @@ func testAccResourceHardwareMappingInit(t *testing.T) (*accTestHardwareMappingFa
}, },
) )
te := initTestEnvironment(t) te := test.InitEnvironment(t)
var data accTestHardwareMappingFakeData var data accTestHardwareMappingFakeData
@ -102,7 +102,7 @@ func TestAccResourceHardwareMappingPCIValidInput(t *testing.T) {
resource.Test( resource.Test(
t, resource.TestCase{ t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Test the "Create" and "Read" implementations where all possible attributes are specified. // Test the "Create" and "Read" implementations where all possible attributes are specified.
{ {
@ -129,7 +129,7 @@ func TestAccResourceHardwareMappingPCIValidInput(t *testing.T) {
data.MapComments[0], data.MapComments[0],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
data.MapIOMMUGroups[0], data.MapIOMMUGroups[0],
te.nodeName, te.NodeName,
data.MapPathsPCI[0], data.MapPathsPCI[0],
data.MapSubsystemIDs[0], data.MapSubsystemIDs[0],
data.MediatedDevices, data.MediatedDevices,
@ -142,7 +142,7 @@ func TestAccResourceHardwareMappingPCIValidInput(t *testing.T) {
"comment": data.MapComments[0], "comment": data.MapComments[0],
"id": data.MapDeviceIDs[0], "id": data.MapDeviceIDs[0],
"iommu_group": strconv.Itoa(int(data.MapIOMMUGroups[0])), "iommu_group": strconv.Itoa(int(data.MapIOMMUGroups[0])),
"node": te.nodeName, "node": te.NodeName,
"path": data.MapPathsPCI[0], "path": data.MapPathsPCI[0],
"subsystem_id": data.MapSubsystemIDs[0], "subsystem_id": data.MapSubsystemIDs[0],
}, },
@ -189,7 +189,7 @@ func TestAccResourceHardwareMappingPCIValidInput(t *testing.T) {
data.MapComments[1], data.MapComments[1],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
data.MapIOMMUGroups[1], data.MapIOMMUGroups[1],
te.nodeName, te.NodeName,
data.MapPathsPCI[1], data.MapPathsPCI[1],
data.MapSubsystemIDs[1], data.MapSubsystemIDs[1],
!data.MediatedDevices, !data.MediatedDevices,
@ -202,7 +202,7 @@ func TestAccResourceHardwareMappingPCIValidInput(t *testing.T) {
"comment": data.MapComments[1], "comment": data.MapComments[1],
"id": data.MapDeviceIDs[0], "id": data.MapDeviceIDs[0],
"iommu_group": strconv.Itoa(int(data.MapIOMMUGroups[1])), "iommu_group": strconv.Itoa(int(data.MapIOMMUGroups[1])),
"node": te.nodeName, "node": te.NodeName,
"path": data.MapPathsPCI[1], "path": data.MapPathsPCI[1],
"subsystem_id": data.MapSubsystemIDs[1], "subsystem_id": data.MapSubsystemIDs[1],
}, },
@ -232,7 +232,7 @@ func TestAccResourceHardwareMappingPCIValidInputMinimal(t *testing.T) {
resource.Test( resource.Test(
t, resource.TestCase{ t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Test the "Create" and "Read" implementations with only the minimum amount of attributes being set. // Test the "Create" and "Read" implementations with only the minimum amount of attributes being set.
{ {
@ -251,7 +251,7 @@ func TestAccResourceHardwareMappingPCIValidInputMinimal(t *testing.T) {
`, `,
data.Names[0], data.Names[0],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
te.nodeName, te.NodeName,
data.MapPathsPCI[0], data.MapPathsPCI[0],
), ),
ConfigStateChecks: []statecheck.StateCheck{ ConfigStateChecks: []statecheck.StateCheck{
@ -273,7 +273,7 @@ func TestAccResourceHardwareMappingPCIValidInputMinimal(t *testing.T) {
resource.TestCheckTypeSetElemNestedAttrs( resource.TestCheckTypeSetElemNestedAttrs(
accTestHardwareMappingNamePCI, "map.*", map[string]string{ accTestHardwareMappingNamePCI, "map.*", map[string]string{
"id": data.MapDeviceIDs[0], "id": data.MapDeviceIDs[0],
"node": te.nodeName, "node": te.NodeName,
"path": data.MapPathsPCI[0], "path": data.MapPathsPCI[0],
}, },
), ),
@ -314,7 +314,7 @@ func TestAccResourceHardwareMappingPCIValidInputMinimal(t *testing.T) {
data.MapComments[1], data.MapComments[1],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
data.MapIOMMUGroups[1], data.MapIOMMUGroups[1],
te.nodeName, te.NodeName,
data.MapPathsPCI[1], data.MapPathsPCI[1],
data.MapSubsystemIDs[1], data.MapSubsystemIDs[1],
!data.MediatedDevices, !data.MediatedDevices,
@ -327,7 +327,7 @@ func TestAccResourceHardwareMappingPCIValidInputMinimal(t *testing.T) {
"comment": data.MapComments[1], "comment": data.MapComments[1],
"id": data.MapDeviceIDs[0], "id": data.MapDeviceIDs[0],
"iommu_group": strconv.Itoa(int(data.MapIOMMUGroups[1])), "iommu_group": strconv.Itoa(int(data.MapIOMMUGroups[1])),
"node": te.nodeName, "node": te.NodeName,
"path": data.MapPathsPCI[1], "path": data.MapPathsPCI[1],
"subsystem_id": data.MapSubsystemIDs[1], "subsystem_id": data.MapSubsystemIDs[1],
}, },
@ -355,7 +355,7 @@ func TestAccResourceHardwareMappingPCIInvalidInput(t *testing.T) {
resource.Test( resource.Test(
t, resource.TestCase{ t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Test the "Create" method implementation where all possible attributes are specified, but an error is expected // Test the "Create" method implementation where all possible attributes are specified, but an error is expected
// when using an invalid device path. // when using an invalid device path.
@ -370,7 +370,7 @@ func TestAccResourceHardwareMappingPCIInvalidInput(t *testing.T) {
// References: // References:
// 1. https://pkg.go.dev/regexp/syntax // 1. https://pkg.go.dev/regexp/syntax
`(?s).*%s(?s).*`, `(?s).*%s(?s).*`,
hwm.ErrResourceMessageInvalidPath(proxmoxtypes.TypePCI), `not a valid Linux device path for hardware mapping of type "`+proxmoxtypes.TypePCI.String()+`"`,
), ),
), ),
Config: fmt.Sprintf( Config: fmt.Sprintf(
@ -397,7 +397,7 @@ func TestAccResourceHardwareMappingPCIInvalidInput(t *testing.T) {
data.Comments[1], data.Comments[1],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
data.MapIOMMUGroups[0], data.MapIOMMUGroups[0],
te.nodeName, te.NodeName,
data.MapSubsystemIDs[0], data.MapSubsystemIDs[0],
data.MediatedDevices, data.MediatedDevices,
), ),
@ -408,7 +408,7 @@ func TestAccResourceHardwareMappingPCIInvalidInput(t *testing.T) {
resource.Test( resource.Test(
t, resource.TestCase{ t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Test the "Create" method implementation where all possible attributes are specified, but an error is expected // Test the "Create" method implementation where all possible attributes are specified, but an error is expected
// when using an invalid device subsystem // when using an invalid device subsystem
@ -439,7 +439,7 @@ func TestAccResourceHardwareMappingPCIInvalidInput(t *testing.T) {
data.Comments[1], data.Comments[1],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
data.MapIOMMUGroups[0], data.MapIOMMUGroups[0],
te.nodeName, te.NodeName,
data.MapPathsPCI[0], data.MapPathsPCI[0],
data.MediatedDevices, data.MediatedDevices,
), ),
@ -459,7 +459,7 @@ func TestAccResourceHardwareMappingUSBValidInput(t *testing.T) {
resource.Test( resource.Test(
t, resource.TestCase{ t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Test the "Create" and "Read" implementations where all possible attributes are specified. // Test the "Create" and "Read" implementations where all possible attributes are specified.
{ {
@ -482,7 +482,7 @@ func TestAccResourceHardwareMappingUSBValidInput(t *testing.T) {
data.Names[0], data.Names[0],
data.MapComments[0], data.MapComments[0],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
te.nodeName, te.NodeName,
data.MapPathsUSB[0], data.MapPathsUSB[0],
), ),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
@ -492,7 +492,7 @@ func TestAccResourceHardwareMappingUSBValidInput(t *testing.T) {
accTestHardwareMappingNameUSB, "map.*", map[string]string{ accTestHardwareMappingNameUSB, "map.*", map[string]string{
"comment": data.MapComments[0], "comment": data.MapComments[0],
"id": data.MapDeviceIDs[0], "id": data.MapDeviceIDs[0],
"node": te.nodeName, "node": te.NodeName,
"path": data.MapPathsUSB[0], "path": data.MapPathsUSB[0],
}, },
), ),
@ -529,7 +529,7 @@ func TestAccResourceHardwareMappingUSBValidInput(t *testing.T) {
data.Names[0], data.Names[0],
data.MapComments[1], data.MapComments[1],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
te.nodeName, te.NodeName,
data.MapPathsUSB[1], data.MapPathsUSB[1],
), ),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
@ -539,7 +539,7 @@ func TestAccResourceHardwareMappingUSBValidInput(t *testing.T) {
accTestHardwareMappingNameUSB, "map.*", map[string]string{ accTestHardwareMappingNameUSB, "map.*", map[string]string{
"comment": data.MapComments[1], "comment": data.MapComments[1],
"id": data.MapDeviceIDs[0], "id": data.MapDeviceIDs[0],
"node": te.nodeName, "node": te.NodeName,
"path": data.MapPathsUSB[1], "path": data.MapPathsUSB[1],
}, },
), ),
@ -563,7 +563,7 @@ func TestAccResourceHardwareMappingUSBValidInputMinimal(t *testing.T) {
resource.Test( resource.Test(
t, resource.TestCase{ t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Test the "Create" and "Read" implementations with only the minimum amount of attributes being set. // Test the "Create" and "Read" implementations with only the minimum amount of attributes being set.
{ {
@ -581,7 +581,7 @@ func TestAccResourceHardwareMappingUSBValidInputMinimal(t *testing.T) {
`, `,
data.Names[0], data.Names[0],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
te.nodeName, te.NodeName,
), ),
ConfigStateChecks: []statecheck.StateCheck{ ConfigStateChecks: []statecheck.StateCheck{
// Optional attributes should all be unset. // Optional attributes should all be unset.
@ -600,7 +600,7 @@ func TestAccResourceHardwareMappingUSBValidInputMinimal(t *testing.T) {
resource.TestCheckTypeSetElemNestedAttrs( resource.TestCheckTypeSetElemNestedAttrs(
accTestHardwareMappingNameUSB, "map.*", map[string]string{ accTestHardwareMappingNameUSB, "map.*", map[string]string{
"id": data.MapDeviceIDs[0], "id": data.MapDeviceIDs[0],
"node": te.nodeName, "node": te.NodeName,
}, },
), ),
resource.TestCheckResourceAttr(accTestHardwareMappingNameUSB, "name", data.Names[0]), resource.TestCheckResourceAttr(accTestHardwareMappingNameUSB, "name", data.Names[0]),
@ -628,7 +628,7 @@ func TestAccResourceHardwareMappingUSBValidInputMinimal(t *testing.T) {
data.Names[0], data.Names[0],
data.Comments[1], data.Comments[1],
data.MapDeviceIDs[1], data.MapDeviceIDs[1],
te.nodeName, te.NodeName,
data.MapPathsUSB[0], data.MapPathsUSB[0],
), ),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
@ -638,7 +638,7 @@ func TestAccResourceHardwareMappingUSBValidInputMinimal(t *testing.T) {
accTestHardwareMappingNameUSB, "map.*", map[string]string{ accTestHardwareMappingNameUSB, "map.*", map[string]string{
"comment": data.Comments[1], "comment": data.Comments[1],
"id": data.MapDeviceIDs[1], "id": data.MapDeviceIDs[1],
"node": te.nodeName, "node": te.NodeName,
"path": data.MapPathsUSB[0], "path": data.MapPathsUSB[0],
}, },
), ),
@ -659,7 +659,7 @@ func TestAccResourceHardwareMappingUSBInvalidInput(t *testing.T) {
resource.Test( resource.Test(
t, resource.TestCase{ t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Test the "Create" method implementation where all possible attributes are specified, but an error is expected // Test the "Create" method implementation where all possible attributes are specified, but an error is expected
// when using an invalid device path. // when using an invalid device path.
@ -684,7 +684,7 @@ func TestAccResourceHardwareMappingUSBInvalidInput(t *testing.T) {
data.Names[0], data.Names[0],
data.Comments[1], data.Comments[1],
data.MapDeviceIDs[0], data.MapDeviceIDs[0],
te.nodeName, te.NodeName,
), ),
ExpectError: regexp.MustCompile(`valid Linux device path for hardware mapping of type "usb"`), ExpectError: regexp.MustCompile(`valid Linux device path for hardware mapping of type "usb"`),
}, },

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package network_test
import ( import (
"fmt" "fmt"
@ -13,10 +13,12 @@ import (
"github.com/brianvoe/gofakeit/v7" "github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
) )
func TestAccResourceLinuxBridge(t *testing.T) { func TestAccResourceLinuxBridge(t *testing.T) {
te := initTestEnvironment(t) te := test.InitEnvironment(t)
iface := fmt.Sprintf("vmbr%d", gofakeit.Number(10, 9999)) iface := fmt.Sprintf("vmbr%d", gofakeit.Number(10, 9999))
ipV4cidr1 := fmt.Sprintf("%s/24", gofakeit.IPv4Address()) ipV4cidr1 := fmt.Sprintf("%s/24", gofakeit.IPv4Address())
@ -24,11 +26,11 @@ func TestAccResourceLinuxBridge(t *testing.T) {
ipV6cidr := "FE80:0000:0000:0000:0202:B3FF:FE1E:8329/64" ipV6cidr := "FE80:0000:0000:0000:0202:B3FF:FE1E:8329/64"
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Create and Read testing // Create and Read testing
{ {
Config: te.renderConfig(fmt.Sprintf(` Config: te.RenderConfig(fmt.Sprintf(`
resource "proxmox_virtual_environment_network_linux_bridge" "test" { resource "proxmox_virtual_environment_network_linux_bridge" "test" {
address = "%s" address = "%s"
autostart = true autostart = true
@ -40,7 +42,7 @@ func TestAccResourceLinuxBridge(t *testing.T) {
} }
`, ipV4cidr1, iface)), `, ipV4cidr1, iface)),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_network_linux_bridge.test", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_network_linux_bridge.test", map[string]string{
"address": ipV4cidr1, "address": ipV4cidr1,
"autostart": "true", "autostart": "true",
"comment": "created by terraform", "comment": "created by terraform",
@ -48,14 +50,14 @@ func TestAccResourceLinuxBridge(t *testing.T) {
"name": iface, "name": iface,
"vlan_aware": "true", "vlan_aware": "true",
}), }),
testResourceAttributesSet("proxmox_virtual_environment_network_linux_bridge.test", []string{ test.ResourceAttributesSet("proxmox_virtual_environment_network_linux_bridge.test", []string{
"id", "id",
}), }),
), ),
}, },
// Update testing // Update testing
{ {
Config: te.renderConfig(fmt.Sprintf(` Config: te.RenderConfig(fmt.Sprintf(`
resource "proxmox_virtual_environment_network_linux_bridge" "test" { resource "proxmox_virtual_environment_network_linux_bridge" "test" {
address = "%s" address = "%s"
address6 = "%s" address6 = "%s"
@ -67,7 +69,7 @@ func TestAccResourceLinuxBridge(t *testing.T) {
vlan_aware = false vlan_aware = false
}`, ipV4cidr2, ipV6cidr, iface)), }`, ipV4cidr2, ipV6cidr, iface)),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_network_linux_bridge.test", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_network_linux_bridge.test", map[string]string{
"address": ipV4cidr2, "address": ipV4cidr2,
"address6": ipV6cidr, "address6": ipV6cidr,
"autostart": "false", "autostart": "false",
@ -75,10 +77,10 @@ func TestAccResourceLinuxBridge(t *testing.T) {
"name": iface, "name": iface,
"vlan_aware": "false", "vlan_aware": "false",
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_network_linux_bridge.test", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_network_linux_bridge.test", []string{
"mtu", "mtu",
}), }),
testResourceAttributesSet("proxmox_virtual_environment_network_linux_bridge.test", []string{ test.ResourceAttributesSet("proxmox_virtual_environment_network_linux_bridge.test", []string{
"id", "id",
}), }),
), ),

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package network_test
import ( import (
"fmt" "fmt"
@ -13,6 +13,8 @@ import (
"github.com/brianvoe/gofakeit/v7" "github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
) )
const ( const (
@ -20,7 +22,7 @@ const (
) )
func TestAccResourceLinuxVLAN(t *testing.T) { func TestAccResourceLinuxVLAN(t *testing.T) {
te := initTestEnvironment(t) te := test.InitEnvironment(t)
iface := "ens18" iface := "ens18"
vlan1 := gofakeit.Number(10, 4094) vlan1 := gofakeit.Number(10, 4094)
@ -29,11 +31,11 @@ func TestAccResourceLinuxVLAN(t *testing.T) {
ipV4cidr := fmt.Sprintf("%s/24", gofakeit.IPv4Address()) ipV4cidr := fmt.Sprintf("%s/24", gofakeit.IPv4Address())
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Create and Read testing // Create and Read testing
{ {
Config: te.renderConfig(testAccResourceLinuxVLANCreatedConfig(iface, vlan1)), Config: te.RenderConfig(testAccResourceLinuxVLANCreatedConfig(iface, vlan1)),
Check: testAccResourceLinuxVLANCreatedCheck(iface, vlan1), Check: testAccResourceLinuxVLANCreatedCheck(iface, vlan1),
}, },
// ImportState testing // ImportState testing
@ -44,7 +46,7 @@ func TestAccResourceLinuxVLAN(t *testing.T) {
}, },
// Create and Read with a custom name // Create and Read with a custom name
{ {
Config: te.renderConfig(testAccResourceLinuxVLANCustomNameCreatedConfig(customName, iface, vlan2)), Config: te.RenderConfig(testAccResourceLinuxVLANCustomNameCreatedConfig(customName, iface, vlan2)),
Check: testAccResourceLinuxVLANCustomNameCreatedCheck(customName, iface, vlan2), Check: testAccResourceLinuxVLANCustomNameCreatedCheck(customName, iface, vlan2),
// PVE API is unreliable. Sometimes it returns a wrong VLAN ID for this second interface. // PVE API is unreliable. Sometimes it returns a wrong VLAN ID for this second interface.
SkipFunc: func() (bool, error) { SkipFunc: func() (bool, error) {
@ -53,7 +55,7 @@ func TestAccResourceLinuxVLAN(t *testing.T) {
}, },
// Update testing // Update testing
{ {
Config: te.renderConfig(testAccResourceLinuxVLANUpdatedConfig(iface, vlan1, ipV4cidr)), Config: te.RenderConfig(testAccResourceLinuxVLANUpdatedConfig(iface, vlan1, ipV4cidr)),
Check: testAccResourceLinuxVLANUpdatedCheck(iface, vlan1, ipV4cidr), Check: testAccResourceLinuxVLANUpdatedCheck(iface, vlan1, ipV4cidr),
}, },
}, },

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package fwprovider_test
import ( import (
"context" "context"
@ -14,6 +14,7 @@ import (
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
"github.com/bpg/terraform-provider-proxmox/proxmox/helpers/ptr" "github.com/bpg/terraform-provider-proxmox/proxmox/helpers/ptr"
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage" "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage"
) )
@ -24,9 +25,9 @@ const (
) )
func TestAccResourceDownloadFile(t *testing.T) { func TestAccResourceDownloadFile(t *testing.T) {
te := initTestEnvironment(t) te := test.InitEnvironment(t)
te.addTemplateVars(map[string]interface{}{ te.AddTemplateVars(map[string]interface{}{
"FakeFileISO": fakeFileISO, "FakeFileISO": fakeFileISO,
"FakeFileQCOW2": fakeFileQCOW2, "FakeFileQCOW2": fakeFileQCOW2,
}) })
@ -36,7 +37,7 @@ func TestAccResourceDownloadFile(t *testing.T) {
steps []resource.TestStep steps []resource.TestStep
}{ }{
{"download qcow2 file", []resource.TestStep{{ {"download qcow2 file", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_download_file" "qcow2_image" { resource "proxmox_virtual_environment_download_file" "qcow2_image" {
content_type = "iso" content_type = "iso"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -48,11 +49,11 @@ func TestAccResourceDownloadFile(t *testing.T) {
overwrite_unmanaged = true overwrite_unmanaged = true
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_download_file.qcow2_image", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_download_file.qcow2_image", map[string]string{
"id": "local:iso/fake_qcow2_file.img", "id": "local:iso/fake_qcow2_file.img",
"content_type": "iso", "content_type": "iso",
"node_name": te.nodeName, "node_name": te.NodeName,
"datastore_id": te.datastoreID, "datastore_id": te.DatastoreID,
"url": fakeFileQCOW2, "url": fakeFileQCOW2,
"file_name": "fake_qcow2_file.img", "file_name": "fake_qcow2_file.img",
"upload_timeout": "600", "upload_timeout": "600",
@ -61,14 +62,14 @@ func TestAccResourceDownloadFile(t *testing.T) {
"checksum": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6", "checksum": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6",
"checksum_algorithm": "sha256", "checksum_algorithm": "sha256",
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_download_file.qcow2_image", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_download_file.qcow2_image", []string{
"decompression_algorithm", "decompression_algorithm",
}), }),
), ),
}}}, }}},
{"download & update iso file", []resource.TestStep{ {"download & update iso file", []resource.TestStep{
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_download_file" "iso_image" { resource "proxmox_virtual_environment_download_file" "iso_image" {
content_type = "iso" content_type = "iso"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -77,17 +78,17 @@ func TestAccResourceDownloadFile(t *testing.T) {
overwrite_unmanaged = true overwrite_unmanaged = true
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{
"id": "local:iso/fake_file.iso", "id": "local:iso/fake_file.iso",
"node_name": te.nodeName, "node_name": te.NodeName,
"datastore_id": te.datastoreID, "datastore_id": te.DatastoreID,
"url": fakeFileISO, "url": fakeFileISO,
"file_name": "fake_file.iso", "file_name": "fake_file.iso",
"upload_timeout": "600", "upload_timeout": "600",
"size": "3", "size": "3",
"verify": "true", "verify": "true",
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_download_file.iso_image", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_download_file.iso_image", []string{
"checksum", "checksum",
"checksum_algorithm", "checksum_algorithm",
"decompression_algorithm", "decompression_algorithm",
@ -95,7 +96,7 @@ func TestAccResourceDownloadFile(t *testing.T) {
), ),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_download_file" "iso_image" { resource "proxmox_virtual_environment_download_file" "iso_image" {
content_type = "iso" content_type = "iso"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -106,18 +107,18 @@ func TestAccResourceDownloadFile(t *testing.T) {
overwrite_unmanaged = true overwrite_unmanaged = true
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{
"id": "local:iso/fake_iso_file.img", "id": "local:iso/fake_iso_file.img",
"content_type": "iso", "content_type": "iso",
"node_name": te.nodeName, "node_name": te.NodeName,
"datastore_id": te.datastoreID, "datastore_id": te.DatastoreID,
"url": fakeFileISO, "url": fakeFileISO,
"file_name": "fake_iso_file.img", "file_name": "fake_iso_file.img",
"upload_timeout": "10000", "upload_timeout": "10000",
"size": "3", "size": "3",
"verify": "true", "verify": "true",
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_download_file.iso_image", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_download_file.iso_image", []string{
"checksum", "checksum",
"checksum_algorithm", "checksum_algorithm",
"decompression_algorithm", "decompression_algorithm",
@ -130,23 +131,23 @@ func TestAccResourceDownloadFile(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel() defer cancel()
_ = te.nodeStorageClient().DeleteDatastoreFile(ctx, "iso/fake_file.iso") //nolint: errcheck _ = te.NodeStorageClient().DeleteDatastoreFile(ctx, "iso/fake_file.iso") //nolint: errcheck
err := te.nodeStorageClient().DownloadFileByURL(ctx, &storage.DownloadURLPostRequestBody{ err := te.NodeStorageClient().DownloadFileByURL(ctx, &storage.DownloadURLPostRequestBody{
Content: ptr.Ptr("iso"), Content: ptr.Ptr("iso"),
FileName: ptr.Ptr("fake_file.iso"), FileName: ptr.Ptr("fake_file.iso"),
Node: ptr.Ptr(te.nodeName), Node: ptr.Ptr(te.NodeName),
Storage: ptr.Ptr(te.datastoreID), Storage: ptr.Ptr(te.DatastoreID),
URL: ptr.Ptr(fakeFileISO), URL: ptr.Ptr(fakeFileISO),
}) })
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
e := te.nodeStorageClient().DeleteDatastoreFile(context.Background(), "iso/fake_file.iso") e := te.NodeStorageClient().DeleteDatastoreFile(context.Background(), "iso/fake_file.iso")
require.NoError(t, e) require.NoError(t, e)
}) })
}, },
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_download_file" "iso_image3" { resource "proxmox_virtual_environment_download_file" "iso_image3" {
content_type = "iso" content_type = "iso"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -156,17 +157,17 @@ func TestAccResourceDownloadFile(t *testing.T) {
overwrite_unmanaged = true overwrite_unmanaged = true
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_download_file.iso_image3", map[string]string{ test.ResourceAttributes("proxmox_virtual_environment_download_file.iso_image3", map[string]string{
"id": "local:iso/fake_iso_file3.iso", "id": "local:iso/fake_iso_file3.iso",
"content_type": "iso", "content_type": "iso",
"node_name": te.nodeName, "node_name": te.NodeName,
"datastore_id": te.datastoreID, "datastore_id": te.DatastoreID,
"url": fakeFileISO, "url": fakeFileISO,
"file_name": "fake_iso_file3.iso", "file_name": "fake_iso_file3.iso",
"size": "3", "size": "3",
"verify": "true", "verify": "true",
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_download_file.iso_image3", []string{ test.NoResourceAttributesSet("proxmox_virtual_environment_download_file.iso_image3", []string{
"checksum", "checksum",
"checksum_algorithm", "checksum_algorithm",
"decompression_algorithm", "decompression_algorithm",
@ -178,7 +179,7 @@ func TestAccResourceDownloadFile(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{ resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package fwprovider_test
import ( import (
"fmt" "fmt"
@ -12,7 +12,7 @@ import (
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider" "github.com/bpg/terraform-provider-proxmox/fwprovider/test"
) )
const accTestClusterOptionsName = "proxmox_virtual_environment_cluster_options.test_options" const accTestClusterOptionsName = "proxmox_virtual_environment_cluster_options.test_options"
@ -20,11 +20,11 @@ const accTestClusterOptionsName = "proxmox_virtual_environment_cluster_options.t
func TestAccResourceClusterOptions(t *testing.T) { func TestAccResourceClusterOptions(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(t) te := test.InitEnvironment(t)
resource.Test( resource.Test(
t, resource.TestCase{ t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Create and Read testing // Create and Read testing
{ {
@ -77,8 +77,8 @@ func testAccResourceClusterOptionsCreatedConfig() string {
} }
} }
`, `,
fwprovider.ClusterOptionsNextIDLowerMinimum, 100,
fwprovider.ClusterOptionsNextIDLowerMaximum, 999999999,
) )
} }
@ -100,12 +100,12 @@ func testAccResourceClusterOptionsCreatedCheck() resource.TestCheckFunc {
resource.TestCheckResourceAttr( resource.TestCheckResourceAttr(
accTestClusterOptionsName, accTestClusterOptionsName,
"next_id.lower", "next_id.lower",
fmt.Sprintf("%d", fwprovider.ClusterOptionsNextIDLowerMinimum), fmt.Sprintf("%d", 100),
), ),
resource.TestCheckResourceAttr( resource.TestCheckResourceAttr(
accTestClusterOptionsName, accTestClusterOptionsName,
"next_id.upper", "next_id.upper",
fmt.Sprintf("%d", fwprovider.ClusterOptionsNextIDLowerMaximum), fmt.Sprintf("%d", 999999999),
), ),
resource.TestCheckResourceAttr(accTestClusterOptionsName, "notify.ha_fencing_mode", "never"), resource.TestCheckResourceAttr(accTestClusterOptionsName, "notify.ha_fencing_mode", "never"),
resource.TestCheckResourceAttr(accTestClusterOptionsName, "notify.ha_fencing_target", "default-matcher"), resource.TestCheckResourceAttr(accTestClusterOptionsName, "notify.ha_fencing_target", "default-matcher"),

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package test
import ( import (
"testing" "testing"
@ -15,16 +15,16 @@ import (
func TestAccDatasourceNode(t *testing.T) { func TestAccDatasourceNode(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(t) te := InitEnvironment(t)
tests := []struct { tests := []struct {
name string name string
steps []resource.TestStep steps []resource.TestStep
}{ }{
{"read node attributes", []resource.TestStep{{ {"read node attributes", []resource.TestStep{{
Config: te.renderConfig(`data "proxmox_virtual_environment_node" "test" { node_name = "{{.NodeName}}" }`), Config: te.RenderConfig(`data "proxmox_virtual_environment_node" "test" { node_name = "{{.NodeName}}" }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributesSet("data.proxmox_virtual_environment_node.test", []string{ ResourceAttributesSet("data.proxmox_virtual_environment_node.test", []string{
"cpu_count", "cpu_count",
"cpu_sockets", "cpu_sockets",
"cpu_model", "cpu_model",
@ -40,7 +40,7 @@ func TestAccDatasourceNode(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{ resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package test
import ( import (
"fmt" "fmt"
@ -15,12 +15,12 @@ import (
) )
func TestAccDatasourceVersion(t *testing.T) { func TestAccDatasourceVersion(t *testing.T) {
te := initTestEnvironment(t) te := InitEnvironment(t)
datasourceName := "data.proxmox_virtual_environment_version.test" datasourceName := "data.proxmox_virtual_environment_version.test"
resource.ParallelTest(t, resource.TestCase{ resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Read testing // Read testing
{ {

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package test
import ( import (
"context" "context"
@ -32,24 +32,24 @@ func TestAccResourceContainer(t *testing.T) { //nolint:wsl
// download fails with 404 or "exit code 8" if run in parallel // download fails with 404 or "exit code 8" if run in parallel
// t.Parallel() // t.Parallel()
te := initTestEnvironment(t) te := InitEnvironment(t)
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: te.renderConfig(testAccResourceContainerCreateConfig(te, false)), Config: te.RenderConfig(testAccResourceContainerCreateConfig(te, false)),
Check: testAccResourceContainerCreateCheck(te), Check: testAccResourceContainerCreateCheck(te),
}, },
{ {
Config: te.renderConfig(testAccResourceContainerCreateConfig(te, true) + testAccResourceContainerCreateCloneConfig(te)), Config: te.RenderConfig(testAccResourceContainerCreateConfig(te, true) + testAccResourceContainerCreateCloneConfig(te)),
Check: testAccResourceContainerCreateCloneCheck(te), Check: testAccResourceContainerCreateCloneCheck(te),
}, },
}, },
}) })
} }
func testAccResourceContainerCreateConfig(te *testEnvironment, isTemplate bool) string { func testAccResourceContainerCreateConfig(te *Environment, isTemplate bool) string {
te.t.Helper() te.t.Helper()
return fmt.Sprintf(` return fmt.Sprintf(`
@ -98,7 +98,7 @@ resource "proxmox_virtual_environment_container" "test_container" {
`, accTestContainerID, isTemplate) `, accTestContainerID, isTemplate)
} }
func testAccResourceContainerCreateCheck(te *testEnvironment) resource.TestCheckFunc { func testAccResourceContainerCreateCheck(te *Environment) resource.TestCheckFunc {
te.t.Helper() te.t.Helper()
return resource.ComposeTestCheckFunc( return resource.ComposeTestCheckFunc(
@ -107,7 +107,7 @@ func testAccResourceContainerCreateCheck(te *testEnvironment) resource.TestCheck
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
err := te.nodeClient().Container(accTestContainerID).WaitForContainerStatus(ctx, "running") err := te.NodeClient().Container(accTestContainerID).WaitForContainerStatus(ctx, "running")
require.NoError(te.t, err, "container did not start") require.NoError(te.t, err, "container did not start")
return nil return nil
@ -115,7 +115,7 @@ func testAccResourceContainerCreateCheck(te *testEnvironment) resource.TestCheck
) )
} }
func testAccResourceContainerCreateCloneConfig(te *testEnvironment) string { func testAccResourceContainerCreateCloneConfig(te *Environment) string {
te.t.Helper() te.t.Helper()
return fmt.Sprintf(` return fmt.Sprintf(`
@ -135,7 +135,7 @@ resource "proxmox_virtual_environment_container" "test_container_clone" {
`, accCloneContainerID) `, accCloneContainerID)
} }
func testAccResourceContainerCreateCloneCheck(te *testEnvironment) resource.TestCheckFunc { func testAccResourceContainerCreateCloneCheck(te *Environment) resource.TestCheckFunc {
te.t.Helper() te.t.Helper()
return resource.ComposeTestCheckFunc( return resource.ComposeTestCheckFunc(
@ -143,7 +143,7 @@ func testAccResourceContainerCreateCloneCheck(te *testEnvironment) resource.Test
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
err := te.nodeClient().Container(accCloneContainerID).WaitForContainerStatus(ctx, "running") err := te.NodeClient().Container(accCloneContainerID).WaitForContainerStatus(ctx, "running")
require.NoError(te.t, err, "container did not start") require.NoError(te.t, err, "container did not start")
return nil return nil

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package test
import ( import (
"context" "context"
@ -36,7 +36,7 @@ func (c *nodeResolver) Resolve(_ context.Context, _ string) (ssh.ProxmoxNode, er
} }
func TestAccResourceFile(t *testing.T) { func TestAccResourceFile(t *testing.T) {
te := initTestEnvironment(t) te := InitEnvironment(t)
snippetRaw := fmt.Sprintf("snippet-raw-%s.txt", gofakeit.Word()) snippetRaw := fmt.Sprintf("snippet-raw-%s.txt", gofakeit.Word())
snippetURL := "https://raw.githubusercontent.com/yaml/yaml-test-suite/main/src/229Q.yaml" snippetURL := "https://raw.githubusercontent.com/yaml/yaml-test-suite/main/src/229Q.yaml"
@ -44,7 +44,7 @@ func TestAccResourceFile(t *testing.T) {
snippetFile2 := strings.ReplaceAll(createFile(t, "snippet-file-2-*.yaml", "test snippet 2 - file").Name(), `\`, `/`) snippetFile2 := strings.ReplaceAll(createFile(t, "snippet-file-2-*.yaml", "test snippet 2 - file").Name(), `\`, `/`)
fileISO := strings.ReplaceAll(createFile(t, "file-*.iso", "pretend it is an ISO").Name(), `\`, `/`) fileISO := strings.ReplaceAll(createFile(t, "file-*.iso", "pretend it is an ISO").Name(), `\`, `/`)
te.addTemplateVars(map[string]interface{}{ te.AddTemplateVars(map[string]interface{}{
"SnippetRaw": snippetRaw, "SnippetRaw": snippetRaw,
"SnippetURL": snippetURL, "SnippetURL": snippetURL,
"SnippetFile1": snippetFile1, "SnippetFile1": snippetFile1,
@ -53,7 +53,7 @@ func TestAccResourceFile(t *testing.T) {
}) })
resource.ParallelTest(t, resource.TestCase{ resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
PreCheck: func() { PreCheck: func() {
uploadSnippetFile(t, snippetFile2) uploadSnippetFile(t, snippetFile2)
t.Cleanup(func() { t.Cleanup(func() {
@ -67,7 +67,7 @@ func TestAccResourceFile(t *testing.T) {
}, },
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test_raw" { resource "proxmox_virtual_environment_file" "test_raw" {
content_type = "snippets" content_type = "snippets"
datastore_id = "local" datastore_id = "local"
@ -79,7 +79,7 @@ func TestAccResourceFile(t *testing.T) {
file_name = "{{.SnippetRaw}}" file_name = "{{.SnippetRaw}}"
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_file.test_raw", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_file.test_raw", map[string]string{
"content_type": "snippets", "content_type": "snippets",
"file_name": snippetRaw, "file_name": snippetRaw,
"source_raw.0.file_name": snippetRaw, "source_raw.0.file_name": snippetRaw,
@ -88,7 +88,7 @@ func TestAccResourceFile(t *testing.T) {
}), }),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -96,14 +96,14 @@ func TestAccResourceFile(t *testing.T) {
path = "{{.SnippetFile1}}" path = "{{.SnippetFile1}}"
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{
"content_type": "snippets", "content_type": "snippets",
"file_name": filepath.Base(snippetFile1), "file_name": filepath.Base(snippetFile1),
"id": fmt.Sprintf("local:snippets/%s", filepath.Base(snippetFile1)), "id": fmt.Sprintf("local:snippets/%s", filepath.Base(snippetFile1)),
}), }),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -111,14 +111,14 @@ func TestAccResourceFile(t *testing.T) {
path = "{{.SnippetURL}}" path = "{{.SnippetURL}}"
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{
"content_type": "snippets", "content_type": "snippets",
"file_name": filepath.Base(snippetURL), "file_name": filepath.Base(snippetURL),
"id": fmt.Sprintf("local:snippets/%s", filepath.Base(snippetURL)), "id": fmt.Sprintf("local:snippets/%s", filepath.Base(snippetURL)),
}), }),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -126,14 +126,14 @@ func TestAccResourceFile(t *testing.T) {
path = "{{.FileISO}}" path = "{{.FileISO}}"
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{
"content_type": "iso", "content_type": "iso",
"file_name": filepath.Base(fileISO), "file_name": filepath.Base(fileISO),
"id": fmt.Sprintf("local:iso/%s", filepath.Base(fileISO)), "id": fmt.Sprintf("local:iso/%s", filepath.Base(fileISO)),
}), }),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -150,7 +150,7 @@ func TestAccResourceFile(t *testing.T) {
ExpectError: regexp.MustCompile("please specify .* - not both"), ExpectError: regexp.MustCompile("please specify .* - not both"),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -162,7 +162,7 @@ func TestAccResourceFile(t *testing.T) {
ExpectError: regexp.MustCompile("failed to determine file name from the URL"), ExpectError: regexp.MustCompile("failed to determine file name from the URL"),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -171,7 +171,7 @@ func TestAccResourceFile(t *testing.T) {
}, },
// Do not allow to overwrite the file // Do not allow to overwrite the file
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -184,7 +184,7 @@ func TestAccResourceFile(t *testing.T) {
}, },
// Allow to overwrite the file by default // Allow to overwrite the file by default
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -192,7 +192,7 @@ func TestAccResourceFile(t *testing.T) {
path = "{{.SnippetFile2}}" path = "{{.SnippetFile2}}"
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{
"content_type": "snippets", "content_type": "snippets",
"file_name": filepath.Base(snippetFile2), "file_name": filepath.Base(snippetFile2),
"id": fmt.Sprintf("local:snippets/%s", filepath.Base(snippetFile2)), "id": fmt.Sprintf("local:snippets/%s", filepath.Base(snippetFile2)),
@ -203,7 +203,7 @@ func TestAccResourceFile(t *testing.T) {
PreConfig: func() { PreConfig: func() {
deleteSnippet(te, filepath.Base(snippetFile1)) deleteSnippet(te, filepath.Base(snippetFile1))
}, },
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
@ -211,7 +211,7 @@ func TestAccResourceFile(t *testing.T) {
path = "{{.SnippetFile1}}" path = "{{.SnippetFile1}}"
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_file.test", map[string]string{
"content_type": "snippets", "content_type": "snippets",
"file_name": filepath.Base(snippetFile1), "file_name": filepath.Base(snippetFile1),
"id": fmt.Sprintf("local:snippets/%s", filepath.Base(snippetFile1)), "id": fmt.Sprintf("local:snippets/%s", filepath.Base(snippetFile1)),
@ -278,9 +278,9 @@ func createFile(t *testing.T, namePattern string, content string) *os.File {
return f return f
} }
func deleteSnippet(te *testEnvironment, fname string) { func deleteSnippet(te *Environment, fname string) {
te.t.Helper() te.t.Helper()
err := te.nodeStorageClient().DeleteDatastoreFile(context.Background(), fmt.Sprintf("snippets/%s", fname)) err := te.NodeStorageClient().DeleteDatastoreFile(context.Background(), fmt.Sprintf("snippets/%s", fname))
require.NoError(te.t, err) require.NoError(te.t, err)
} }

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package test
import ( import (
"testing" "testing"
@ -13,14 +13,14 @@ import (
) )
func TestAccResourceClusterFirewall(t *testing.T) { func TestAccResourceClusterFirewall(t *testing.T) {
te := initTestEnvironment(t) te := InitEnvironment(t)
tests := []struct { tests := []struct {
name string name string
steps []resource.TestStep steps []resource.TestStep
}{ }{
{"rules1", []resource.TestStep{{ {"rules1", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_firewall_rules" "rules1" { resource "proxmox_virtual_environment_firewall_rules" "rules1" {
rule { rule {
type = "in" type = "in"
@ -32,7 +32,7 @@ func TestAccResourceClusterFirewall(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_firewall_rules.rules1", map[string]string{ ResourceAttributes("proxmox_virtual_environment_firewall_rules.rules1", map[string]string{
"rule.0.type": "in", "rule.0.type": "in",
"rule.0.action": "ACCEPT", "rule.0.action": "ACCEPT",
"rule.0.iface": "vmbr0", "rule.0.iface": "vmbr0",
@ -40,7 +40,7 @@ func TestAccResourceClusterFirewall(t *testing.T) {
"rule.0.proto": "tcp", "rule.0.proto": "tcp",
"rule.0.comment": "PVE Admin Interface", "rule.0.comment": "PVE Admin Interface",
}), }),
testNoResourceAttributesSet("proxmox_virtual_environment_firewall_rules.rules1", []string{ NoResourceAttributesSet("proxmox_virtual_environment_firewall_rules.rules1", []string{
"node_name", "node_name",
}), }),
), ),
@ -50,7 +50,7 @@ func TestAccResourceClusterFirewall(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{ resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package test
import ( import (
"testing" "testing"
@ -15,7 +15,7 @@ import (
func TestAccResourceTime(t *testing.T) { func TestAccResourceTime(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(t) te := InitEnvironment(t)
tests := []struct { tests := []struct {
name string name string
@ -23,29 +23,29 @@ func TestAccResourceTime(t *testing.T) {
}{ }{
{"change timezone", []resource.TestStep{ {"change timezone", []resource.TestStep{
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_time" "node_time" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_time" "node_time" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
time_zone = "America/New_York" time_zone = "America/New_York"
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_time.node_time", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_time.node_time", map[string]string{
"time_zone": "America/New_York", "time_zone": "America/New_York",
}), }),
}, },
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_time" "node_time" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_time" "node_time" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
time_zone = "UTC" time_zone = "UTC"
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_time.node_time", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_time.node_time", map[string]string{
"time_zone": "UTC", "time_zone": "UTC",
}), }),
}, },
{ {
Config: te.renderConfig(`resource "proxmox_virtual_environment_time" "node_time" { Config: te.RenderConfig(`resource "proxmox_virtual_environment_time" "node_time" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
time_zone = "UTC" time_zone = "UTC"
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_time.node_time", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_time.node_time", map[string]string{
"time_zone": "UTC", "time_zone": "UTC",
}), }),
}, },
@ -55,7 +55,7 @@ func TestAccResourceTime(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package test
import ( import (
"testing" "testing"
@ -15,14 +15,14 @@ import (
func TestAccResourceVM(t *testing.T) { func TestAccResourceVM(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(t) te := InitEnvironment(t)
tests := []struct { tests := []struct {
name string name string
step []resource.TestStep step []resource.TestStep
}{ }{
{"multiline description", []resource.TestStep{{ {"multiline description", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm1" { resource "proxmox_virtual_environment_vm" "test_vm1" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -34,13 +34,13 @@ func TestAccResourceVM(t *testing.T) {
EOT EOT
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm1", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm1", map[string]string{
"description": "my\ndescription\nvalue", "description": "my\ndescription\nvalue",
}), }),
), ),
}}}, }}},
{"single line description", []resource.TestStep{{ {"single line description", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm2" { resource "proxmox_virtual_environment_vm" "test_vm2" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -48,13 +48,13 @@ func TestAccResourceVM(t *testing.T) {
description = "my description value" description = "my description value"
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm2", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm2", map[string]string{
"description": "my description value", "description": "my description value",
}), }),
), ),
}}}, }}},
{"no description", []resource.TestStep{{ {"no description", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm3" { resource "proxmox_virtual_environment_vm" "test_vm3" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -62,14 +62,14 @@ func TestAccResourceVM(t *testing.T) {
description = "" description = ""
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm3", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm3", map[string]string{
"description": "", "description": "",
}), }),
), ),
}}}, }}},
{ {
"protection", []resource.TestStep{{ "protection", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm4" { resource "proxmox_virtual_environment_vm" "test_vm4" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -77,12 +77,12 @@ func TestAccResourceVM(t *testing.T) {
protection = true protection = true
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm4", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm4", map[string]string{
"protection": "true", "protection": "true",
}), }),
), ),
}, { }, {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm4" { resource "proxmox_virtual_environment_vm" "test_vm4" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -90,7 +90,7 @@ func TestAccResourceVM(t *testing.T) {
protection = false protection = false
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm4", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm4", map[string]string{
"protection": "false", "protection": "false",
}), }),
), ),
@ -98,7 +98,7 @@ func TestAccResourceVM(t *testing.T) {
}, },
{ {
"update cpu block", []resource.TestStep{{ "update cpu block", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm5" { resource "proxmox_virtual_environment_vm" "test_vm5" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -108,12 +108,12 @@ func TestAccResourceVM(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm5", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm5", map[string]string{
"cpu.0.sockets": "1", "cpu.0.sockets": "1",
}), }),
), ),
}, { }, {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm5" { resource "proxmox_virtual_environment_vm" "test_vm5" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -123,7 +123,7 @@ func TestAccResourceVM(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm5", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm5", map[string]string{
"cpu.0.sockets": "1", "cpu.0.sockets": "1",
}), }),
), ),
@ -131,7 +131,7 @@ func TestAccResourceVM(t *testing.T) {
}, },
{ {
"update memory block", []resource.TestStep{{ "update memory block", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm6" { resource "proxmox_virtual_environment_vm" "test_vm6" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -141,12 +141,12 @@ func TestAccResourceVM(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm6", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm6", map[string]string{
"memory.0.dedicated": "2048", "memory.0.dedicated": "2048",
}), }),
), ),
}, { }, {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm6" { resource "proxmox_virtual_environment_vm" "test_vm6" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -156,7 +156,7 @@ func TestAccResourceVM(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm6", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm6", map[string]string{
"memory.0.dedicated": "1024", "memory.0.dedicated": "1024",
}), }),
), ),
@ -169,7 +169,7 @@ func TestAccResourceVM(t *testing.T) {
t.Parallel() t.Parallel()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.step, Steps: tt.step,
}) })
}) })
@ -177,27 +177,27 @@ func TestAccResourceVM(t *testing.T) {
} }
func TestAccResourceVMInitialization(t *testing.T) { func TestAccResourceVMInitialization(t *testing.T) {
te := initTestEnvironment(t) te := InitEnvironment(t)
tests := []struct { tests := []struct {
name string name string
step []resource.TestStep step []resource.TestStep
}{ }{
{"custom cloud-init: use SCSI interface", []resource.TestStep{{ {"custom cloud-init: use SCSI interface", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "cloud_config" { resource "proxmox_virtual_environment_file" "cloud_config" {
content_type = "snippets" content_type = "snippets"
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
source_raw { source_raw {
data = <<-EOF data = <<-EOF
#cloud-config #cloud-config
runcmd: runcmd:
- apt update - apt update
- apt install -y qemu-guest-agent - apt install -y qemu-guest-agent
- systemctl enable qemu-guest-agent - systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent - systemctl start qemu-guest-agent
EOF EOF
file_name = "cloud-config.yaml" file_name = "cloud-config.yaml"
} }
} }
@ -247,7 +247,7 @@ func TestAccResourceVMInitialization(t *testing.T) {
}`), }`),
}}}, }}},
{"native cloud-init: do not upgrade packages", []resource.TestStep{{ {"native cloud-init: do not upgrade packages", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm_cloudinit3" { resource "proxmox_virtual_environment_vm" "test_vm_cloudinit3" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -256,7 +256,7 @@ func TestAccResourceVMInitialization(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm_cloudinit3", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm_cloudinit3", map[string]string{
"initialization.0.upgrade": "false", "initialization.0.upgrade": "false",
}), }),
), ),
@ -266,7 +266,7 @@ func TestAccResourceVMInitialization(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.step, Steps: tt.step,
}) })
}) })
@ -274,27 +274,27 @@ func TestAccResourceVMInitialization(t *testing.T) {
} }
func TestAccResourceVMNetwork(t *testing.T) { func TestAccResourceVMNetwork(t *testing.T) {
te := initTestEnvironment(t) te := InitEnvironment(t)
tests := []struct { tests := []struct {
name string name string
step []resource.TestStep step []resource.TestStep
}{ }{
{"network interfaces", []resource.TestStep{{ {"network interfaces", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_file" "cloud_config" { resource "proxmox_virtual_environment_file" "cloud_config" {
content_type = "snippets" content_type = "snippets"
datastore_id = "local" datastore_id = "local"
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
source_raw { source_raw {
data = <<EOF data = <<-EOF
#cloud-config #cloud-config
runcmd: runcmd:
- apt update - apt update
- apt install -y qemu-guest-agent - apt install -y qemu-guest-agent
- systemctl enable qemu-guest-agent - systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent - systemctl start qemu-guest-agent
EOF EOF
file_name = "cloud-config.yaml" file_name = "cloud-config.yaml"
} }
} }
@ -341,7 +341,7 @@ EOF
overwrite_unmanaged = true overwrite_unmanaged = true
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network1", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm_network1", map[string]string{
"ipv4_addresses.#": "2", "ipv4_addresses.#": "2",
"mac_addresses.#": "2", "mac_addresses.#": "2",
"network_device.0.bridge": "vmbr0", "network_device.0.bridge": "vmbr0",
@ -350,7 +350,7 @@ EOF
), ),
}}}, }}},
{"network device disconnected", []resource.TestStep{{ {"network device disconnected", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm_network2" { resource "proxmox_virtual_environment_vm" "test_vm_network2" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -360,13 +360,13 @@ EOF
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network2", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm_network2", map[string]string{
"network_device.0.bridge": "vmbr0", "network_device.0.bridge": "vmbr0",
"network_device.0.disconnected": "false", "network_device.0.disconnected": "false",
}), }),
), ),
}, { }, {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_vm_network2" { resource "proxmox_virtual_environment_vm" "test_vm_network2" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -377,7 +377,7 @@ EOF
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network2", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_vm_network2", map[string]string{
"network_device.0.bridge": "vmbr0", "network_device.0.bridge": "vmbr0",
"network_device.0.disconnected": "true", "network_device.0.disconnected": "true",
}), }),
@ -390,7 +390,7 @@ EOF
t.Parallel() t.Parallel()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.step, Steps: tt.step,
}) })
}) })
@ -400,7 +400,7 @@ EOF
func TestAccResourceVMDisks(t *testing.T) { func TestAccResourceVMDisks(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(t) te := InitEnvironment(t)
tests := []struct { tests := []struct {
name string name string
@ -408,7 +408,7 @@ func TestAccResourceVMDisks(t *testing.T) {
}{ }{
{"create disk with default parameters, then update it", []resource.TestStep{ {"create disk with default parameters, then update it", []resource.TestStep{
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_disk1" { resource "proxmox_virtual_environment_vm" "test_disk1" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -423,7 +423,7 @@ func TestAccResourceVMDisks(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{
"disk.0.aio": "io_uring", "disk.0.aio": "io_uring",
"disk.0.backup": "true", "disk.0.backup": "true",
"disk.0.cache": "none", "disk.0.cache": "none",
@ -441,7 +441,7 @@ func TestAccResourceVMDisks(t *testing.T) {
), ),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_disk1" { resource "proxmox_virtual_environment_vm" "test_disk1" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -464,7 +464,7 @@ func TestAccResourceVMDisks(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{
"disk.0.aio": "native", "disk.0.aio": "native",
"disk.0.backup": "true", "disk.0.backup": "true",
"disk.0.cache": "none", "disk.0.cache": "none",
@ -487,7 +487,7 @@ func TestAccResourceVMDisks(t *testing.T) {
}, },
}}, }},
{"create disk from an image", []resource.TestStep{{ {"create disk from an image", []resource.TestStep{{
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_download_file" "test_disk2_image" { resource "proxmox_virtual_environment_download_file" "test_disk2_image" {
content_type = "iso" content_type = "iso"
datastore_id = "local" datastore_id = "local"
@ -509,7 +509,7 @@ func TestAccResourceVMDisks(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_disk2", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_disk2", map[string]string{
"disk.0.cache": "none", "disk.0.cache": "none",
"disk.0.datastore_id": "local-lvm", "disk.0.datastore_id": "local-lvm",
"disk.0.discard": "on", "disk.0.discard": "on",
@ -524,7 +524,7 @@ func TestAccResourceVMDisks(t *testing.T) {
}}}, }}},
{"clone default disk without overrides", []resource.TestStep{ {"clone default disk without overrides", []resource.TestStep{
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_disk3_template" { resource "proxmox_virtual_environment_vm" "test_disk3_template" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -550,7 +550,7 @@ func TestAccResourceVMDisks(t *testing.T) {
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
// fully cloned disk, does not have any attributes in state // fully cloned disk, does not have any attributes in state
resource.TestCheckNoResourceAttr("proxmox_virtual_environment_vm.test_disk3", "disk.0"), resource.TestCheckNoResourceAttr("proxmox_virtual_environment_vm.test_disk3", "disk.0"),
testResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{}), ResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{}),
), ),
}, },
{ {
@ -559,7 +559,7 @@ func TestAccResourceVMDisks(t *testing.T) {
}}, }},
{"multiple disks", []resource.TestStep{ {"multiple disks", []resource.TestStep{
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_disk4" { resource "proxmox_virtual_environment_vm" "test_disk4" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -579,7 +579,7 @@ func TestAccResourceVMDisks(t *testing.T) {
size = 8 size = 8
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_vm.test_disk4", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_vm.test_disk4", map[string]string{
"disk.0.interface": "virtio0", "disk.0.interface": "virtio0",
"disk.0.path_in_datastore": `vm-\d+-disk-1`, "disk.0.path_in_datastore": `vm-\d+-disk-1`,
"disk.1.interface": "scsi0", "disk.1.interface": "scsi0",
@ -593,7 +593,7 @@ func TestAccResourceVMDisks(t *testing.T) {
{"cdrom", []resource.TestStep{ {"cdrom", []resource.TestStep{
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_cdrom" { resource "proxmox_virtual_environment_vm" "test_cdrom" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -603,7 +603,7 @@ func TestAccResourceVMDisks(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_cdrom", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_cdrom", map[string]string{
"cdrom.0.enabled": "true", "cdrom.0.enabled": "true",
}), }),
), ),
@ -614,7 +614,7 @@ func TestAccResourceVMDisks(t *testing.T) {
}}, }},
{"efi disk", []resource.TestStep{ {"efi disk", []resource.TestStep{
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_efi_disk" { resource "proxmox_virtual_environment_vm" "test_efi_disk" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -626,7 +626,7 @@ func TestAccResourceVMDisks(t *testing.T) {
} }
}`), }`),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_efi_disk", map[string]string{ ResourceAttributes("proxmox_virtual_environment_vm.test_efi_disk", map[string]string{
"efi_disk.0.datastore_id": "local-lvm", "efi_disk.0.datastore_id": "local-lvm",
"efi_disk.0.type": "4m", "efi_disk.0.type": "4m",
}), }),
@ -638,7 +638,7 @@ func TestAccResourceVMDisks(t *testing.T) {
}}, }},
{"ide disks", []resource.TestStep{ {"ide disks", []resource.TestStep{
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_disks" { resource "proxmox_virtual_environment_vm" "test_disks" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -651,13 +651,13 @@ func TestAccResourceVMDisks(t *testing.T) {
size = 8 size = 8
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_vm.test_disks", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_vm.test_disks", map[string]string{
"disk.0.interface": "ide0", "disk.0.interface": "ide0",
"disk.0.path_in_datastore": `vm-\d+-disk-0`, "disk.0.path_in_datastore": `vm-\d+-disk-0`,
}), }),
}, },
{ {
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_disks" { resource "proxmox_virtual_environment_vm" "test_disks" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -676,7 +676,7 @@ func TestAccResourceVMDisks(t *testing.T) {
size = 8 size = 8
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_vm.test_disks", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_vm.test_disks", map[string]string{
"disk.#": "2", "disk.#": "2",
}), }),
}, },
@ -690,7 +690,7 @@ func TestAccResourceVMDisks(t *testing.T) {
// this test is failing because of https://github.com/bpg/terraform-provider-proxmox/issues/873 // this test is failing because of https://github.com/bpg/terraform-provider-proxmox/issues/873
return true, nil return true, nil
}, },
Config: te.renderConfig(` Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_disk3_template" { resource "proxmox_virtual_environment_vm" "test_disk3_template" {
node_name = "{{.NodeName}}" node_name = "{{.NodeName}}"
started = false started = false
@ -721,7 +721,7 @@ func TestAccResourceVMDisks(t *testing.T) {
//size = 10 //size = 10
} }
}`), }`),
Check: testResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{ Check: ResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{
"disk.0.datastore_id": "local-lvm", "disk.0.datastore_id": "local-lvm",
"disk.0.discard": "on", "disk.0.discard": "on",
"disk.0.file_format": "raw", "disk.0.file_format": "raw",
@ -737,6 +737,49 @@ func TestAccResourceVMDisks(t *testing.T) {
Destroy: false, Destroy: false,
}, },
}}, }},
{"clone with disk resize", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm" "test_disk3_template" {
node_name = "{{.NodeName}}"
started = false
name = "test-disk3-template"
template = "true"
disk {
file_format = "raw"
datastore_id = "local-lvm"
interface = "virtio0"
size = 8
}
}
resource "proxmox_virtual_environment_vm" "test_disk3" {
node_name = "{{.NodeName}}"
started = false
name = "test-disk3"
clone {
vm_id = proxmox_virtual_environment_vm.test_disk3_template.id
}
disk {
datastore_id = "local-lvm"
interface = "virtio0"
size = 10
}
}`),
Check: resource.ComposeTestCheckFunc(
ResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{
"disk.0.datastore_id": "local-lvm",
"disk.0.interface": "virtio0",
"disk.0.size": "10",
}),
),
},
{
RefreshState: true,
},
}},
} }
for _, tt := range tests { for _, tt := range tests {
@ -744,7 +787,7 @@ func TestAccResourceVMDisks(t *testing.T) {
t.Parallel() t.Parallel()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders, ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -1,4 +1,4 @@
package tests package test
import ( import (
"bytes" "bytes"
@ -17,29 +17,31 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/bpg/terraform-provider-proxmox/fwprovider"
"github.com/bpg/terraform-provider-proxmox/proxmox/access" "github.com/bpg/terraform-provider-proxmox/proxmox/access"
sdkV2provider "github.com/bpg/terraform-provider-proxmox/proxmoxtf/provider" sdkV2provider "github.com/bpg/terraform-provider-proxmox/proxmoxtf/provider"
"github.com/bpg/terraform-provider-proxmox/fwprovider"
"github.com/bpg/terraform-provider-proxmox/proxmox/api" "github.com/bpg/terraform-provider-proxmox/proxmox/api"
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes" "github.com/bpg/terraform-provider-proxmox/proxmox/nodes"
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage" "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage"
"github.com/bpg/terraform-provider-proxmox/utils" "github.com/bpg/terraform-provider-proxmox/utils"
) )
type testEnvironment struct { // Environment is a test environment for acceptance tests.
type Environment struct {
t *testing.T t *testing.T
templateVars map[string]any templateVars map[string]any
providerConfig string providerConfig string
nodeName string NodeName string
datastoreID string DatastoreID string
accProviders map[string]func() (tfprotov6.ProviderServer, error) AccProviders map[string]func() (tfprotov6.ProviderServer, error)
once sync.Once once sync.Once
c api.Client c api.Client
} }
func initTestEnvironment(t *testing.T) *testEnvironment { // InitEnvironment initializes a new test environment for acceptance tests.
func InitEnvironment(t *testing.T) *Environment {
t.Helper() t.Helper()
nodeName := utils.GetAnyStringEnv("PROXMOX_VE_ACC_NODE_NAME") nodeName := utils.GetAnyStringEnv("PROXMOX_VE_ACC_NODE_NAME")
@ -75,7 +77,7 @@ provider "proxmox" {
const datastoreID = "local" const datastoreID = "local"
return &testEnvironment{ return &Environment{
t: t, t: t,
templateVars: map[string]any{ templateVars: map[string]any{
"ProviderConfig": pc, "ProviderConfig": pc,
@ -83,23 +85,23 @@ provider "proxmox" {
"DatastoreID": datastoreID, "DatastoreID": datastoreID,
}, },
providerConfig: pc, providerConfig: pc,
nodeName: nodeName, NodeName: nodeName,
datastoreID: datastoreID, DatastoreID: datastoreID,
accProviders: muxProviders(t), AccProviders: muxProviders(t),
} }
} }
// addTemplateVars adds the given variables to the template variables of the current test environment. // AddTemplateVars adds the given variables to the template variables of the current test environment.
// Please note that NodeName and ProviderConfig are reserved keys, they are set by the test environment // Please note that NodeName and ProviderConfig are reserved keys, they are set by the test environment
// and cannot be overridden. // and cannot be overridden.
func (e *testEnvironment) addTemplateVars(vars map[string]any) { func (e *Environment) AddTemplateVars(vars map[string]any) {
for k, v := range vars { for k, v := range vars {
e.templateVars[k] = v e.templateVars[k] = v
} }
} }
// renderConfig renders the given configuration with for the current test environment using template engine. // RenderConfig renders the given configuration with for the current test environment using template engine.
func (e *testEnvironment) renderConfig(cfg string) string { func (e *Environment) RenderConfig(cfg string) string {
tmpl, err := template.New("config").Parse("{{.ProviderConfig}}" + cfg) tmpl, err := template.New("config").Parse("{{.ProviderConfig}}" + cfg)
require.NoError(e.t, err) require.NoError(e.t, err)
@ -110,7 +112,8 @@ func (e *testEnvironment) renderConfig(cfg string) string {
return buf.String() return buf.String()
} }
func (e *testEnvironment) client() api.Client { // Client returns a new API client for the test environment.
func (e *Environment) Client() api.Client {
if e.c == nil { if e.c == nil {
e.once.Do( e.once.Do(
func() { func() {
@ -139,16 +142,19 @@ func (e *testEnvironment) client() api.Client {
return e.c return e.c
} }
func (e *testEnvironment) accessClient() *access.Client { // AccessClient returns a new access client for the test environment.
return &access.Client{Client: e.client()} func (e *Environment) AccessClient() *access.Client {
return &access.Client{Client: e.Client()}
} }
func (e *testEnvironment) nodeClient() *nodes.Client { // NodeClient returns a new nodes client for the test environment.
return &nodes.Client{Client: e.client(), NodeName: e.nodeName} func (e *Environment) NodeClient() *nodes.Client {
return &nodes.Client{Client: e.Client(), NodeName: e.NodeName}
} }
func (e *testEnvironment) nodeStorageClient() *storage.Client { // NodeStorageClient returns a new storage client for the test environment.
return &storage.Client{Client: e.nodeClient(), StorageName: e.datastoreID} func (e *Environment) NodeStorageClient() *storage.Client {
return &storage.Client{Client: e.NodeClient(), StorageName: e.DatastoreID}
} }
// testAccMuxProviders returns a map of mux servers for the acceptance tests. // testAccMuxProviders returns a map of mux servers for the acceptance tests.

View File

@ -4,7 +4,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
package tests package test
import ( import (
"fmt" "fmt"
@ -14,7 +14,8 @@ import (
"github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-plugin-testing/terraform"
) )
func testResourceAttributes(res string, attrs map[string]string) resource.TestCheckFunc { // ResourceAttributes is a helper function to test resource attributes.
func ResourceAttributes(res string, attrs map[string]string) resource.TestCheckFunc {
return func(s *terraform.State) error { return func(s *terraform.State) error {
for k, v := range attrs { for k, v := range attrs {
if v == "" { if v == "" {
@ -43,7 +44,8 @@ func testResourceAttributes(res string, attrs map[string]string) resource.TestCh
} }
} }
func testNoResourceAttributesSet(res string, attrs []string) resource.TestCheckFunc { // NoResourceAttributesSet is a helper function to test that no resource attributes are set.
func NoResourceAttributesSet(res string, attrs []string) resource.TestCheckFunc {
return func(s *terraform.State) error { return func(s *terraform.State) error {
for _, k := range attrs { for _, k := range attrs {
if err := resource.TestCheckNoResourceAttr(res, k)(s); err != nil { if err := resource.TestCheckNoResourceAttr(res, k)(s); err != nil {
@ -55,7 +57,8 @@ func testNoResourceAttributesSet(res string, attrs []string) resource.TestCheckF
} }
} }
func testResourceAttributesSet(res string, attrs []string) resource.TestCheckFunc { // ResourceAttributesSet is a helper function to test that all resource attributes are set.
func ResourceAttributesSet(res string, attrs []string) resource.TestCheckFunc {
return func(s *terraform.State) error { return func(s *terraform.State) error {
for _, k := range attrs { for _, k := range attrs {
if err := resource.TestCheckResourceAttrSet(res, k)(s); err != nil { if err := resource.TestCheckResourceAttrSet(res, k)(s); err != nil {

View File

@ -1,455 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package tests
import (
"regexp"
"strconv"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)
func TestAccResourceVM2(t *testing.T) {
t.Parallel()
te := initTestEnvironment(t)
vmID := gofakeit.IntRange(90000, 100000)
te.addTemplateVars(map[string]any{
"VMID": vmID,
})
tests := []struct {
name string
steps []resource.TestStep
}{
{"create minimal VM", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"node_name": te.nodeName,
}),
testResourceAttributesSet("proxmox_virtual_environment_vm2.test_vm", []string{
"id",
}),
),
}}},
{"create minimal VM with ID", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
id = {{.VMID}}
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"node_name": te.nodeName,
"id": strconv.Itoa(vmID),
}),
),
}}},
{"set an invalid VM name", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "not a valid DNS name"
}`),
ExpectError: regexp.MustCompile(`name must be a valid DNS name`),
}}},
{"set, update, import with primitive fields", []resource.TestStep{
{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-vm"
description = "test description"
}`),
Check: testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"name": "test-vm",
"description": "test description",
}),
},
{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-vm"
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"name": "test-vm",
}),
testNoResourceAttributesSet("proxmox_virtual_environment_vm2.test_vm", []string{
"description",
}),
),
},
{
ResourceName: "proxmox_virtual_environment_vm2.test_vm",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: te.nodeName + "/",
},
}},
{"set, update, import with tags", []resource.TestStep{
{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-tags"
tags = ["tag2", "tag1"]
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm", "tags.*", "tag1"),
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm", "tags.*", "tag2"),
),
},
{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-tags"
tags = ["tag1"]
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm2.test_vm", "tags.#", "1"),
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm", "tags.*", "tag1"),
),
},
{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-tags"
// no tags
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm2.test_vm", "tags.#", "1"),
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm", "tags.*", "tag1"),
),
},
{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-tags"
tags = []
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm2.test_vm", "tags.#", "0"),
),
},
}},
{"a VM can't have empty tags", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
tags = ["", "tag1"]
}`),
ExpectError: regexp.MustCompile(`string length must be at least 1, got: 0`),
}}},
{"a VM can't have empty tags", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
tags = [" ", "tag1"]
}`),
ExpectError: regexp.MustCompile(`must be a non-empty and non-whitespace string`),
}}},
{"multiline description", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
description = trimspace(<<-EOT
my
description
value
EOT
)
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"description": "my\ndescription\nvalue",
}),
),
}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders,
Steps: tt.steps,
})
})
}
}
func TestAccResourceVM2CPU(t *testing.T) {
t.Parallel()
te := initTestEnvironment(t)
tests := []struct {
name string
steps []resource.TestStep
}{
{"create VM with no cpu params", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
// default values that are set by PVE if not specified
"cpu.cores": "1",
"cpu.sockets": "1",
"cpu.type": "kvm64",
}),
),
}}},
{"create VM with some cpu params", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
cpu = {
cores = 2
sockets = 2
type = "host"
flags = ["+aes"]
}
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "2",
"cpu.sockets": "2",
"cpu.type": "host",
"cpu.flags.#": "1",
"cpu.flags.0": `\+aes`,
}),
),
}}},
{"create VM with all cpu params and then update them", []resource.TestStep{
{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
cpu = {
# affinity = "0-1" only root can set affinity
# architecture = "x86_64" only root can set architecture
cores = 2
hotplugged = 2
limit = 64
numa = false
sockets = 2
type = "host"
units = 1024
flags = ["+aes"]
}
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "2",
"cpu.hotplugged": "2",
"cpu.limit": "64",
"cpu.numa": "false",
"cpu.sockets": "2",
"cpu.type": "host",
"cpu.units": "1024",
}),
),
},
{ // now update the cpu params and check if they are updated
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
cpu = {
cores = 4
hotplugged = 2
limit = null # setting to null is the same as removal
# numa = false
# sockets = 2 remove sockets, so it should fall back to 1 (PVE default)
# type = "host" remove type, so it should fall back to kvm64 (PVE default)
units = 2048
# flags = ["+aes"]
}
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "4",
"cpu.hotplugged": "2",
"cpu.sockets": "1", // default value, but it is a special case.
"cpu.type": "kvm64", // default value, but it is a special case.
"cpu.units": "2048",
}),
testNoResourceAttributesSet("proxmox_virtual_environment_vm2.test_vm", []string{
"cpu.limit", // other defaults are not set in the state
"cpu.numa",
"cpu.flags",
}),
),
},
{
RefreshState: true,
},
}},
{"clone VM with some cpu params", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "template_vm" {
node_name = "{{.NodeName}}"
name = "template-cpu"
cpu = {
cores = 2
sockets = 2
type = "host"
}
}
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
clone = {
id = proxmox_virtual_environment_vm2.template_vm.id
}
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "2",
"cpu.sockets": "2",
"cpu.type": "host",
}),
),
}}},
{"clone VM with some cpu params and updating them in the clone", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "template_vm" {
node_name = "{{.NodeName}}"
name = "template-cpu"
cpu = {
cores = 2
sockets = 2
type = "host"
}
}
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
clone = {
id = proxmox_virtual_environment_vm2.template_vm.id
}
cpu = {
cores = 4
units = 1024
}
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "4",
"cpu.sockets": "2",
"cpu.type": "host",
"cpu.units": "1024",
}),
),
}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders,
Steps: tt.steps,
})
})
}
}
func TestAccResourceVM2Clone(t *testing.T) {
t.Parallel()
te := initTestEnvironment(t)
vmID := gofakeit.IntRange(90000, 100000)
te.addTemplateVars(map[string]any{
"VMID": vmID,
})
tests := []struct {
name string
steps []resource.TestStep
}{
{"create a clone from template", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "template"
description = "template description"
template = true
}
resource "proxmox_virtual_environment_vm2" "test_vm_clone" {
node_name = "{{.NodeName}}"
name = "clone"
clone = {
id = proxmox_virtual_environment_vm2.test_vm.id
}
}`),
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"template": "true",
}),
testResourceAttributes("proxmox_virtual_environment_vm2.test_vm_clone", map[string]string{
// name is overwritten
"name": "clone",
}),
testNoResourceAttributesSet("proxmox_virtual_environment_vm2.test_vm_clone", []string{
// description is not copied
"description",
}),
),
}}},
{"tags are copied to the clone", []resource.TestStep{{
Config: te.renderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
template = true
tags = ["tag1", "tag2"]
}
resource "proxmox_virtual_environment_vm2" "test_vm_clone" {
node_name = "{{.NodeName}}"
clone = {
id = proxmox_virtual_environment_vm2.test_vm.id
}
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm_clone", "tags.*", "tag1"),
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm_clone", "tags.*", "tag2"),
),
}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.accProviders,
Steps: tt.steps,
})
})
}
}

View File

@ -2,110 +2,19 @@ package cpu
import ( import (
"context" "context"
"fmt"
"reflect" "reflect"
"github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-go/tftypes"
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms" "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms"
proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types" proxmoxtypes "github.com/bpg/terraform-provider-proxmox/proxmox/types"
) )
var ( // Value represents the type for CPU settings.
_ basetypes.ObjectTypable = Type{} type Value = types.Object
_ basetypes.ObjectValuable = Value{}
)
// Type is an attribute type that represents CPU settings.
type Type struct {
basetypes.ObjectType
}
// String returns a human-readable representation of the type.
func (t Type) String() string {
return "cpu.Type"
}
// ValueFromObject returns a Value given a basetypes.ObjectValue.
func (t Type) ValueFromObject(
_ context.Context,
in basetypes.ObjectValue,
) (basetypes.ObjectValuable, diag.Diagnostics) {
value := Value{
Object: in,
}
return value, nil
}
// ValueFromTerraform returns a Value given a tftypes.Value.
// Value embeds the types.Object value returned from calling ValueFromTerraform on the
// types.ObjectType embedded in Type.
func (t Type) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
val, err := t.ObjectType.ValueFromTerraform(ctx, in)
if err != nil {
return nil, fmt.Errorf("failed to convert value to types.Object: %w", err)
}
obj, ok := val.(types.Object)
if !ok {
return nil, fmt.Errorf("%T cannot be used as types.Object", val)
}
return Value{obj}, nil
}
// ValueType returns the associated Value type for debugging.
func (t Type) ValueType(context.Context) attr.Value {
// It does not need to be a fully valid implementation of the type.
return Value{}
}
// Equal returns true if `candidate` is also a Type and has the same
// AttributeTypes.
func (t Type) Equal(candidate attr.Type) bool {
other, ok := candidate.(Type)
if !ok {
return false
}
return t.ObjectType.Equal(other.ObjectType)
}
// Value represents an object containing values to be used as CPU settings.
type Value struct {
types.Object
}
// Equal returns true if the Value is considered semantically equal
// (same type and same value) to the attr.Value passed as an argument.
func (v Value) Equal(c attr.Value) bool {
other, ok := c.(Value)
if !ok {
return false
}
return v.Object.Equal(other.Object)
}
// ToObjectValue returns the underlying ObjectValue.
func (v Value) ToObjectValue(_ context.Context) (basetypes.ObjectValue, diag.Diagnostics) {
return v.Object, nil
}
// Type returns a Type with the same attribute types as `t`.
func (v Value) Type(ctx context.Context) attr.Type {
return Type{
types.ObjectType{
AttrTypes: v.AttributeTypes(ctx),
},
}
}
// NewValue returns a new Value with the given CPU settings from the PVE API. // NewValue returns a new Value with the given CPU settings from the PVE API.
func NewValue(ctx context.Context, config *vms.GetResponseData, diags *diag.Diagnostics) Value { func NewValue(ctx context.Context, config *vms.GetResponseData, diags *diag.Diagnostics) Value {
@ -147,20 +56,20 @@ func NewValue(ctx context.Context, config *vms.GetResponseData, diags *diag.Diag
obj, d := types.ObjectValueFrom(ctx, attributeTypes(), cpu) obj, d := types.ObjectValueFrom(ctx, attributeTypes(), cpu)
diags.Append(d...) diags.Append(d...)
return Value{obj} return obj
} }
// FillCreateBody fills the CreateRequestBody with the CPU settings from the Value. // FillCreateBody fills the CreateRequestBody with the CPU settings from the Value.
// //
// In the 'create' context, v is the plan. // In the 'create' context, v is the plan.
func (v Value) FillCreateBody(ctx context.Context, body *vms.CreateRequestBody, diags *diag.Diagnostics) { func FillCreateBody(ctx context.Context, planValue Value, body *vms.CreateRequestBody, diags *diag.Diagnostics) {
var plan Model var plan Model
if v.IsNull() || v.IsUnknown() { if planValue.IsNull() || planValue.IsUnknown() {
return return
} }
d := v.Object.As(ctx, &plan, basetypes.ObjectAsOptions{}) d := planValue.As(ctx, &plan, basetypes.ObjectAsOptions{})
diags.Append(d...) diags.Append(d...)
if d.HasError() { if d.HasError() {
@ -215,22 +124,22 @@ func (v Value) FillCreateBody(ctx context.Context, body *vms.CreateRequestBody,
// FillUpdateBody fills the UpdateRequestBody with the CPU settings from the Value. // FillUpdateBody fills the UpdateRequestBody with the CPU settings from the Value.
// //
// In the 'update' context, v is the plan and stateValue is the current state. // In the 'update' context, v is the plan and stateValue is the current state.
func (v Value) FillUpdateBody( func FillUpdateBody(
ctx context.Context, ctx context.Context,
stateValue Value, planValue, stateValue Value,
updateBody *vms.UpdateRequestBody, updateBody *vms.UpdateRequestBody,
isClone bool, isClone bool,
diags *diag.Diagnostics, diags *diag.Diagnostics,
) { ) {
var plan, state Model var plan, state Model
if v.IsNull() || v.IsUnknown() || v.Equal(stateValue) { if planValue.IsNull() || planValue.IsUnknown() || planValue.Equal(stateValue) {
return return
} }
d := v.Object.As(ctx, &plan, basetypes.ObjectAsOptions{}) d := planValue.As(ctx, &plan, basetypes.ObjectAsOptions{})
diags.Append(d...) diags.Append(d...)
d = stateValue.Object.As(ctx, &state, basetypes.ObjectAsOptions{}) d = stateValue.As(ctx, &state, basetypes.ObjectAsOptions{})
diags.Append(d...) diags.Append(d...)
if diags.HasError() { if diags.HasError() {

View File

@ -18,10 +18,8 @@ import (
// Schema defines the schema for the CPU resource. // Schema defines the schema for the CPU resource.
func Schema() schema.Attribute { func Schema() schema.Attribute {
return schema.SingleNestedAttribute{ return schema.SingleNestedAttribute{
CustomType: Type{ CustomType: basetypes.ObjectType{
ObjectType: basetypes.ObjectType{ AttrTypes: attributeTypes(),
AttrTypes: attributeTypes(),
},
}, },
Description: "The CPU configuration.", Description: "The CPU configuration.",
Optional: true, Optional: true,

View File

@ -0,0 +1,190 @@
package cpu_test
import (
"testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
)
func TestAccResourceVM2CPU(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
tests := []struct {
name string
steps []resource.TestStep
}{
{"create VM with no cpu params", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
// default values that are set by PVE if not specified
"cpu.cores": "1",
"cpu.sockets": "1",
"cpu.type": "kvm64",
}),
),
}}},
{"create VM with some cpu params", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
cpu = {
cores = 2
sockets = 2
type = "host"
flags = ["+aes"]
}
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "2",
"cpu.sockets": "2",
"cpu.type": "host",
"cpu.flags.#": "1",
"cpu.flags.0": `\+aes`,
}),
),
}}},
{"create VM with all cpu params and then update them", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
cpu = {
# affinity = "0-1" only root can set affinity
# architecture = "x86_64" only root can set architecture
cores = 2
hotplugged = 2
limit = 64
numa = false
sockets = 2
type = "host"
units = 1024
flags = ["+aes"]
}
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "2",
"cpu.hotplugged": "2",
"cpu.limit": "64",
"cpu.numa": "false",
"cpu.sockets": "2",
"cpu.type": "host",
"cpu.units": "1024",
}),
),
},
{ // now update the cpu params and check if they are updated
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
cpu = {
cores = 4
hotplugged = 2
limit = null # setting to null is the same as removal
# numa = false
# sockets = 2 remove sockets, so it should fall back to 1 (PVE default)
# type = "host" remove type, so it should fall back to kvm64 (PVE default)
units = 2048
# flags = ["+aes"]
}
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "4",
"cpu.hotplugged": "2",
"cpu.sockets": "1", // default value, but it is a special case.
"cpu.type": "kvm64", // default value, but it is a special case.
"cpu.units": "2048",
}),
test.NoResourceAttributesSet("proxmox_virtual_environment_vm2.test_vm", []string{
"cpu.limit", // other defaults are not set in the state
"cpu.numa",
"cpu.flags",
}),
),
},
{
RefreshState: true,
},
}},
{"clone VM with some cpu params", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "template_vm" {
node_name = "{{.NodeName}}"
name = "template-cpu"
cpu = {
cores = 2
sockets = 2
type = "host"
}
}
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
clone = {
id = proxmox_virtual_environment_vm2.template_vm.id
}
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "2",
"cpu.sockets": "2",
"cpu.type": "host",
}),
),
}}},
{"clone VM with some cpu params and updating them in the clone", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "template_vm" {
node_name = "{{.NodeName}}"
name = "template-cpu"
cpu = {
cores = 2
sockets = 2
type = "host"
}
}
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-cpu"
clone = {
id = proxmox_virtual_environment_vm2.template_vm.id
}
cpu = {
cores = 4
units = 1024
}
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"cpu.cores": "4",
"cpu.sockets": "2",
"cpu.type": "host",
"cpu.units": "1024",
}),
),
}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps,
})
})
}
}

View File

@ -146,7 +146,7 @@ func (r *Resource) create(ctx context.Context, plan Model, diags *diag.Diagnosti
} }
// fill out create body fields with values from other resource blocks // fill out create body fields with values from other resource blocks
plan.CPU.FillCreateBody(ctx, createBody, diags) cpu.FillCreateBody(ctx, plan.CPU, createBody, diags)
if diags.HasError() { if diags.HasError() {
return return
@ -320,7 +320,7 @@ func (r *Resource) update(ctx context.Context, plan, state Model, isClone bool,
} }
} }
plan.CPU.FillUpdateBody(ctx, state.CPU, updateBody, isClone, diags) cpu.FillUpdateBody(ctx, plan.CPU, state.CPU, updateBody, isClone, diags)
if !updateBody.IsEmpty() { if !updateBody.IsEmpty() {
updateBody.VMID = int(plan.ID.ValueInt64()) updateBody.VMID = int(plan.ID.ValueInt64())

View File

@ -9,11 +9,13 @@ import (
) )
// Model represents the VM model. // Model represents the VM model.
//
// Note: for computed fields / blocks we have to use an Object type (or an alias),
// or a custom type in order to hold an unknown value.
type Model struct { type Model struct {
Description types.String `tfsdk:"description"` Description types.String `tfsdk:"description"`
// for computed fields / blocks we have to use custom type? (because of unknown?) CPU cpu.Value `tfsdk:"cpu"`
CPU cpu.Value `tfsdk:"cpu"` Clone *struct {
Clone *struct {
ID types.Int64 `tfsdk:"id"` ID types.Int64 `tfsdk:"id"`
Retries types.Int64 `tfsdk:"retries"` Retries types.Int64 `tfsdk:"retries"`
} `tfsdk:"clone"` } `tfsdk:"clone"`

View File

@ -0,0 +1,276 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package vm_test
import (
"regexp"
"strconv"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
)
func TestAccResourceVM(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
vmID := gofakeit.IntRange(90000, 100000)
te.AddTemplateVars(map[string]any{
"VMID": vmID,
})
tests := []struct {
name string
steps []resource.TestStep
}{
{"create minimal VM", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"node_name": te.NodeName,
}),
test.ResourceAttributesSet("proxmox_virtual_environment_vm2.test_vm", []string{
"id",
}),
),
}}},
{"create minimal VM with ID", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
id = {{.VMID}}
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"node_name": te.NodeName,
"id": strconv.Itoa(vmID),
}),
),
}}},
{"set an invalid VM name", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "not a valid DNS name"
}`),
ExpectError: regexp.MustCompile(`name must be a valid DNS name`),
}}},
{"set, update, import with primitive fields", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-vm"
description = "test description"
}`),
Check: test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"name": "test-vm",
"description": "test description",
}),
},
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-vm"
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"name": "test-vm",
}),
test.NoResourceAttributesSet("proxmox_virtual_environment_vm2.test_vm", []string{
"description",
}),
),
},
{
ResourceName: "proxmox_virtual_environment_vm2.test_vm",
ImportState: true,
ImportStateVerify: true,
ImportStateIdPrefix: te.NodeName + "/",
},
}},
{"set, update, import with tags", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-tags"
tags = ["tag2", "tag1"]
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm", "tags.*", "tag1"),
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm", "tags.*", "tag2"),
),
},
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-tags"
tags = ["tag1"]
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm2.test_vm", "tags.#", "1"),
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm", "tags.*", "tag1"),
),
},
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-tags"
// no tags
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm2.test_vm", "tags.#", "1"),
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm", "tags.*", "tag1"),
),
},
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "test-tags"
tags = []
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("proxmox_virtual_environment_vm2.test_vm", "tags.#", "0"),
),
},
}},
{"a VM can't have empty tags", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
tags = ["", "tag1"]
}`),
ExpectError: regexp.MustCompile(`string length must be at least 1, got: 0`),
}}},
{"a VM can't have empty tags", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
tags = [" ", "tag1"]
}`),
ExpectError: regexp.MustCompile(`must be a non-empty and non-whitespace string`),
}}},
{"multiline description", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
description = trimspace(<<-EOT
my
description
value
EOT
)
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"description": "my\ndescription\nvalue",
}),
),
}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps,
})
})
}
}
func TestAccResourceVM2Clone(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
vmID := gofakeit.IntRange(90000, 100000)
te.AddTemplateVars(map[string]any{
"VMID": vmID,
})
tests := []struct {
name string
steps []resource.TestStep
}{
{"create a clone from template", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
name = "template"
description = "template description"
template = true
}
resource "proxmox_virtual_environment_vm2" "test_vm_clone" {
node_name = "{{.NodeName}}"
name = "clone"
clone = {
id = proxmox_virtual_environment_vm2.test_vm.id
}
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm", map[string]string{
"template": "true",
}),
test.ResourceAttributes("proxmox_virtual_environment_vm2.test_vm_clone", map[string]string{
// name is overwritten
"name": "clone",
}),
test.NoResourceAttributesSet("proxmox_virtual_environment_vm2.test_vm_clone", []string{
// description is not copied
"description",
}),
),
}}},
{"tags are copied to the clone", []resource.TestStep{{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_vm2" "test_vm" {
node_name = "{{.NodeName}}"
template = true
tags = ["tag1", "tag2"]
}
resource "proxmox_virtual_environment_vm2" "test_vm_clone" {
node_name = "{{.NodeName}}"
clone = {
id = proxmox_virtual_environment_vm2.test_vm.id
}
}`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm_clone", "tags.*", "tag1"),
resource.TestCheckTypeSetElemAttr("proxmox_virtual_environment_vm2.test_vm_clone", "tags.*", "tag2"),
),
}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource.ParallelTest(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.steps,
})
})
}
}

View File

@ -14,12 +14,10 @@ description: |-
-> Many attributes are marked as **optional** _and_ **computed** in the schema, -> Many attributes are marked as **optional** _and_ **computed** in the schema,
hence you may seem added to the plan with "(known after apply)" status, even if they are not set in the configuration. hence you may seem added to the plan with "(known after apply)" status, even if they are not set in the configuration.
This is done to support the `clone` operation, when a VM is created from an existing one, This is done to support the `clone` operation, when a VM is created from an existing VM or template,
and attributes of the original VM are copied to the new one.<br><br> and the source attributes are copied to the clone.<br><br>
Computed attributes allow the provider to set those attributes without user input. Computed attributes allow the provider to set those attributes without user input.
The attributes are marked as optional to allow the user to set (or overwrite) them if needed. The attributes are also marked as optional to allow the practitioner to set (or overwrite) them if needed.
In order to remove the computed attribute from the plan, you can set it to an empty value (e.g. `""` for string, `[]` for collection).
{{ if .HasExample -}} {{ if .HasExample -}}
## Example Usage ## Example Usage