0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-06-30 02:31:10 +00:00

chore: improve acceptance tests on CI (#1173)

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
Pavel Boldyrev 2024-04-07 00:41:57 -04:00 committed by GitHub
parent 24daca5941
commit 268c861649
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 370 additions and 318 deletions

View File

@ -99,11 +99,3 @@ jobs:
filters: | filters: |
go: go:
- '**/*.go' - '**/*.go'
# - name: Invoke acceptance tests workflow
# if: ${{ steps.filter.outputs.go == 'true' }}
# uses: benc-uk/workflow-dispatch@v1
# with:
# workflow: testacc.yml
# ref: ${{ github.event.pull_request.head.ref }}
# inputs: '{"ref": "${{ github.head_ref }}" }'

View File

@ -7,14 +7,27 @@ on:
description: 'Branch or tag to run tests against' description: 'Branch or tag to run tests against'
required: true required: true
default: 'main' default: 'main'
push:
branches:
- main
jobs: jobs:
acceptance: acceptance:
strategy: strategy:
max-parallel: 1 fail-fast: false
matrix: matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
terraform: [ 1.6 ] terraform: [ 1.6 ]
os: [ ubuntu-latest, windows-latest, macos-latest ]
include:
- os: ubuntu-latest
node: pve1
port: 13451
- os: windows-latest
node: pve2
port: 13452
- os: macos-latest
node: pve3
port: 13453
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
environment: pve-acc environment: pve-acc
steps: steps:
@ -53,5 +66,7 @@ jobs:
PROXMOX_VE_SSH_AGENT: false PROXMOX_VE_SSH_AGENT: false
PROXMOX_VE_SSH_USERNAME: "terraform" PROXMOX_VE_SSH_USERNAME: "terraform"
PROXMOX_VE_SSH_PRIVATE_KEY: "${{ secrets.PROXMOX_VE_SSH_PRIVATE_KEY }}" PROXMOX_VE_SSH_PRIVATE_KEY: "${{ secrets.PROXMOX_VE_SSH_PRIVATE_KEY }}"
PROXMOX_VE_ACC_NODE_NAME: ${{ matrix.node }}
PROXMOX_VE_ACC_NODE_SSH_ADDRESS: ${{ secrets.PROXMOX_VE_HOST }}
PROXMOX_VE_ACC_NODE_SSH_PORT: ${{ matrix.port }}
run: make testacc run: make testacc

View File

@ -61,6 +61,9 @@ PROXMOX_VE_API_TOKEN="root@pam!<token name>=<token value>"
PROXMOX_VE_ENDPOINT="https://<pve instance>:8006/" PROXMOX_VE_ENDPOINT="https://<pve instance>:8006/"
PROXMOX_VE_SSH_AGENT="true" PROXMOX_VE_SSH_AGENT="true"
PROXMOX_VE_SSH_USERNAME="root" PROXMOX_VE_SSH_USERNAME="root"
# optionally, youcan override the default node name and ssh address
#PROXMOX_VE_ACC_NODE_NAME="pve1"
#PROXMOX_VE_ACC_NODE_SSH_ADDRESS="10.0.0.11"
``` ```
Then use `make testacc` to run the acceptance tests. Then use `make testacc` to run the acceptance tests.

View File

@ -7,7 +7,6 @@
package tests package tests
import ( import (
"context"
"fmt" "fmt"
"testing" "testing"
@ -17,12 +16,14 @@ import (
func TestAccDatasourceNode(t *testing.T) { func TestAccDatasourceNode(t *testing.T) {
t.Parallel() t.Parallel()
te := initTestEnvironment(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: fmt.Sprintf(`data "proxmox_virtual_environment_node" "test" { node_name = "%s" }`, accTestNodeName), Config: fmt.Sprintf(`data "proxmox_virtual_environment_node" "test" { node_name = "%s" }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributesSet("data.proxmox_virtual_environment_node.test", []string{ testResourceAttributesSet("data.proxmox_virtual_environment_node.test", []string{
"cpu_count", "cpu_count",
@ -37,14 +38,12 @@ func TestAccDatasourceNode(t *testing.T) {
}}}, }}},
} }
accProviders := testAccMuxProviders(context.Background(), 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) {
t.Parallel() t.Parallel()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -7,7 +7,6 @@
package tests package tests
import ( import (
"context"
"fmt" "fmt"
"strings" "strings"
"testing" "testing"
@ -18,12 +17,12 @@ import (
func TestAccDatasourceVersion(t *testing.T) { func TestAccDatasourceVersion(t *testing.T) {
t.Parallel() t.Parallel()
accProviders := testAccMuxProviders(context.Background(), t) te := initTestEnvironment(t)
datasourceName := "data.proxmox_virtual_environment_version.test" datasourceName := "data.proxmox_virtual_environment_version.test"
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Read testing // Read testing
{ {

View File

@ -28,35 +28,40 @@ var (
accCloneContainerID = 200000 + rand.Intn(99999) //nolint:gosec accCloneContainerID = 200000 + rand.Intn(99999) //nolint:gosec
) )
func TestAccResourceContainer(t *testing.T) { func TestAccResourceContainer(t *testing.T) { //nolint:wsl
accProviders := testAccMuxProviders(context.Background(), t) // download fails with 404 or "exit code 8" if run in parallel
// t.Parallel()
te := initTestEnvironment(t)
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccResourceContainerCreateConfig(false), Config: testAccResourceContainerCreateConfig(te, false),
Check: testAccResourceContainerCreateCheck(t), Check: testAccResourceContainerCreateCheck(te),
}, },
{ {
Config: testAccResourceContainerCreateConfig(true) + testAccResourceContainerCreateCloneConfig(), Config: testAccResourceContainerCreateConfig(te, true) + testAccResourceContainerCreateCloneConfig(te),
Check: testAccResourceContainerCreateCloneCheck(t), Check: testAccResourceContainerCreateCloneCheck(te),
}, },
}, },
}) })
} }
func testAccResourceContainerCreateConfig(isTemplate bool) string { func testAccResourceContainerCreateConfig(te *testEnvironment, isTemplate bool) string {
te.t.Helper()
return fmt.Sprintf(` return fmt.Sprintf(`
resource "proxmox_virtual_environment_download_file" "ubuntu_container_template" { resource "proxmox_virtual_environment_download_file" "ubuntu_container_template" {
content_type = "vztmpl" content_type = "vztmpl"
datastore_id = "local" datastore_id = "local"
node_name = "pve" node_name = "%[1]s"
url = "http://download.proxmox.com/images/system/ubuntu-23.04-standard_23.04-1_amd64.tar.zst" url = "http://download.proxmox.com/images/system/ubuntu-23.04-standard_23.04-1_amd64.tar.zst"
overwrite_unmanaged = true overwrite_unmanaged = true
} }
resource "proxmox_virtual_environment_container" "test_container" { resource "proxmox_virtual_environment_container" "test_container" {
node_name = "%s" node_name = "%[1]s"
vm_id = %d vm_id = %d
template = %t template = %t
@ -90,24 +95,26 @@ resource "proxmox_virtual_environment_container" "test_container" {
type = "ubuntu" type = "ubuntu"
} }
} }
`, accTestNodeName, accTestContainerID, isTemplate) `, te.nodeName, accTestContainerID, isTemplate)
} }
func testAccResourceContainerCreateCheck(t *testing.T) resource.TestCheckFunc { func testAccResourceContainerCreateCheck(te *testEnvironment) resource.TestCheckFunc {
t.Helper() te.t.Helper()
return resource.ComposeTestCheckFunc( return resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(accTestContainerName, "description", "my\ndescription\nvalue\n"), resource.TestCheckResourceAttr(accTestContainerName, "description", "my\ndescription\nvalue\n"),
func(*terraform.State) error { func(*terraform.State) error {
err := getNodesClient().Container(accTestContainerID).WaitForContainerStatus(context.Background(), "running", 10, 1) err := te.nodeClient().Container(accTestContainerID).WaitForContainerStatus(context.Background(), "running", 10, 1)
require.NoError(t, err, "container did not start") require.NoError(te.t, err, "container did not start")
return nil return nil
}, },
) )
} }
func testAccResourceContainerCreateCloneConfig() string { func testAccResourceContainerCreateCloneConfig(te *testEnvironment) string {
te.t.Helper()
return fmt.Sprintf(` return fmt.Sprintf(`
resource "proxmox_virtual_environment_container" "test_container_clone" { resource "proxmox_virtual_environment_container" "test_container_clone" {
depends_on = [proxmox_virtual_environment_container.test_container] depends_on = [proxmox_virtual_environment_container.test_container]
@ -123,16 +130,16 @@ resource "proxmox_virtual_environment_container" "test_container_clone" {
hostname = "test-clone" hostname = "test-clone"
} }
} }
`, accTestNodeName, accCloneContainerID) `, te.nodeName, accCloneContainerID)
} }
func testAccResourceContainerCreateCloneCheck(t *testing.T) resource.TestCheckFunc { func testAccResourceContainerCreateCloneCheck(te *testEnvironment) resource.TestCheckFunc {
t.Helper() te.t.Helper()
return resource.ComposeTestCheckFunc( return resource.ComposeTestCheckFunc(
func(*terraform.State) error { func(*terraform.State) error {
err := getNodesClient().Container(accCloneContainerID).WaitForContainerStatus(context.Background(), "running", 10, 1) err := te.nodeClient().Container(accCloneContainerID).WaitForContainerStatus(context.Background(), "running", 10, 1)
require.NoError(t, err, "container did not start") require.NoError(te.t, err, "container did not start")
return nil return nil
}, },

View File

@ -24,6 +24,8 @@ const (
) )
func TestAccResourceDownloadFile(t *testing.T) { func TestAccResourceDownloadFile(t *testing.T) {
te := initTestEnvironment(t)
tests := []struct { tests := []struct {
name string name string
steps []resource.TestStep steps []resource.TestStep
@ -37,11 +39,11 @@ func TestAccResourceDownloadFile(t *testing.T) {
url = "%s" url = "%s"
overwrite_unmanaged = true overwrite_unmanaged = true
} }
`, accTestNodeName, accTestStorageName, fakeFileISO), `, te.nodeName, accTestStorageName, fakeFileISO),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{ testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{
"id": "local:iso/fake_file.iso", "id": "local:iso/fake_file.iso",
"node_name": accTestNodeName, "node_name": te.nodeName,
"datastore_id": accTestStorageName, "datastore_id": accTestStorageName,
"url": fakeFileISO, "url": fakeFileISO,
"file_name": "fake_file.iso", "file_name": "fake_file.iso",
@ -68,12 +70,12 @@ func TestAccResourceDownloadFile(t *testing.T) {
checksum_algorithm = "sha256" checksum_algorithm = "sha256"
overwrite_unmanaged = true overwrite_unmanaged = true
} }
`, accTestNodeName, accTestStorageName, fakeFileQCOW2), `, te.nodeName, accTestStorageName, fakeFileQCOW2),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_download_file.qcow2_image", map[string]string{ testResourceAttributes("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": accTestNodeName, "node_name": te.nodeName,
"datastore_id": accTestStorageName, "datastore_id": accTestStorageName,
"url": fakeFileQCOW2, "url": fakeFileQCOW2,
"file_name": "fake_qcow2_file.img", "file_name": "fake_qcow2_file.img",
@ -99,12 +101,12 @@ func TestAccResourceDownloadFile(t *testing.T) {
upload_timeout = 10000 upload_timeout = 10000
overwrite_unmanaged = true overwrite_unmanaged = true
} }
`, accTestNodeName, accTestStorageName, fakeFileISO), `, te.nodeName, accTestStorageName, fakeFileISO),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{ testResourceAttributes("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": accTestNodeName, "node_name": te.nodeName,
"datastore_id": accTestStorageName, "datastore_id": accTestStorageName,
"url": fakeFileISO, "url": fakeFileISO,
"file_name": "fake_iso_file.img", "file_name": "fake_iso_file.img",
@ -121,16 +123,16 @@ func TestAccResourceDownloadFile(t *testing.T) {
}}}, }}},
{"override unmanaged file", []resource.TestStep{{ {"override unmanaged file", []resource.TestStep{{
PreConfig: func() { PreConfig: func() {
err := getNodeStorageClient().DownloadFileByURL(context.Background(), &storage.DownloadURLPostRequestBody{ err := te.nodeStorageClient().DownloadFileByURL(context.Background(), &storage.DownloadURLPostRequestBody{
Content: types.StrPtr("iso"), Content: types.StrPtr("iso"),
FileName: types.StrPtr("fake_file.iso"), FileName: types.StrPtr("fake_file.iso"),
Node: types.StrPtr(accTestNodeName), Node: types.StrPtr(te.nodeName),
Storage: types.StrPtr(accTestStorageName), Storage: types.StrPtr(accTestStorageName),
URL: types.StrPtr(fakeFileISO), URL: types.StrPtr(fakeFileISO),
}, 600) }, 600)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
err := getNodeStorageClient().DeleteDatastoreFile(context.Background(), "iso/fake_file.iso") err := te.nodeStorageClient().DeleteDatastoreFile(context.Background(), "iso/fake_file.iso")
require.NoError(t, err) require.NoError(t, err)
}) })
}, },
@ -142,12 +144,12 @@ func TestAccResourceDownloadFile(t *testing.T) {
url = "%s" url = "%s"
overwrite_unmanaged = true overwrite_unmanaged = true
} }
`, accTestNodeName, accTestStorageName, fakeFileISO), `, te.nodeName, accTestStorageName, fakeFileISO),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{ testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{
"id": "local:iso/fake_file.iso", "id": "local:iso/fake_file.iso",
"content_type": "iso", "content_type": "iso",
"node_name": accTestNodeName, "node_name": te.nodeName,
"datastore_id": accTestStorageName, "datastore_id": accTestStorageName,
"url": fakeFileISO, "url": fakeFileISO,
"file_name": "fake_file.iso", "file_name": "fake_file.iso",
@ -163,12 +165,10 @@ func TestAccResourceDownloadFile(t *testing.T) {
}}}, }}},
} }
accProviders := testAccMuxProviders(context.Background(), 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: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -43,7 +43,7 @@ func (c *nodeResolver) Resolve(_ context.Context, _ string) (ssh.ProxmoxNode, er
func TestAccResourceFile(t *testing.T) { func TestAccResourceFile(t *testing.T) {
t.Parallel() t.Parallel()
accProviders := testAccMuxProviders(context.Background(), t) te := initTestEnvironment(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"
@ -52,55 +52,55 @@ func TestAccResourceFile(t *testing.T) {
fileISO := createFile(t, "file-*.iso", "pretend it is an ISO") fileISO := createFile(t, "file-*.iso", "pretend it is an ISO")
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders, ProtoV6ProviderFactories: te.accProviders,
PreCheck: func() { PreCheck: func() {
uploadSnippetFile(t, snippetFile2) uploadSnippetFile(t, snippetFile2)
}, },
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccResourceFileSnippetRawCreatedConfig(t, snippetRaw), Config: testAccResourceFileSnippetRawCreatedConfig(te, snippetRaw),
Check: testAccResourceFileSnippetRawCreatedCheck(snippetRaw), Check: testAccResourceFileSnippetRawCreatedCheck(snippetRaw),
}, },
{ {
Config: testAccResourceFileCreatedConfig(t, snippetFile1.Name()), Config: testAccResourceFileCreatedConfig(te, snippetFile1.Name()),
Check: testAccResourceFileCreatedCheck("snippets", snippetFile1.Name()), Check: testAccResourceFileCreatedCheck("snippets", snippetFile1.Name()),
}, },
{ {
Config: testAccResourceFileCreatedConfig(t, snippetURL), Config: testAccResourceFileCreatedConfig(te, snippetURL),
Check: testAccResourceFileCreatedCheck("snippets", snippetURL), Check: testAccResourceFileCreatedCheck("snippets", snippetURL),
}, },
{ {
Config: testAccResourceFileCreatedConfig(t, fileISO.Name()), Config: testAccResourceFileCreatedConfig(te, fileISO.Name()),
Check: testAccResourceFileCreatedCheck("iso", fileISO.Name()), Check: testAccResourceFileCreatedCheck("iso", fileISO.Name()),
}, },
{ {
Config: testAccResourceFileTwoSourcesCreatedConfig(t), Config: testAccResourceFileTwoSourcesCreatedConfig(te),
ExpectError: regexp.MustCompile("please specify .* - not both"), ExpectError: regexp.MustCompile("please specify .* - not both"),
}, },
{ {
Config: testAccResourceFileCreatedConfig(t, "https://github.com", "content_type = \"iso\""), Config: testAccResourceFileCreatedConfig(te, "https://github.com", "content_type = \"iso\""),
ExpectError: regexp.MustCompile("failed to determine file name from the URL"), ExpectError: regexp.MustCompile("failed to determine file name from the URL"),
}, },
{ {
Config: testAccResourceFileMissingSourceConfig(t), Config: testAccResourceFileMissingSourceConfig(te),
ExpectError: regexp.MustCompile("missing argument"), ExpectError: regexp.MustCompile("missing argument"),
}, },
// Do not allow to overwrite the file // Do not allow to overwrite the file
{ {
Config: testAccResourceFileCreatedConfig(t, snippetFile2.Name(), "overwrite = false"), Config: testAccResourceFileCreatedConfig(te, snippetFile2.Name(), "overwrite = false"),
ExpectError: regexp.MustCompile("already exists"), ExpectError: regexp.MustCompile("already exists"),
}, },
// Allow to overwrite the file by default // Allow to overwrite the file by default
{ {
Config: testAccResourceFileCreatedConfig(t, snippetFile2.Name()), Config: testAccResourceFileCreatedConfig(te, snippetFile2.Name()),
Check: testAccResourceFileCreatedCheck("snippets", snippetFile2.Name()), Check: testAccResourceFileCreatedCheck("snippets", snippetFile2.Name()),
}, },
// Update testing // Update testing
{ {
PreConfig: func() { PreConfig: func() {
deleteSnippet(t, filepath.Base(snippetFile1.Name())) deleteSnippet(te, filepath.Base(snippetFile1.Name()))
}, },
Config: testAccResourceFileSnippetUpdateConfig(t, snippetFile1.Name()), Config: testAccResourceFileSnippetUpdateConfig(te, snippetFile1.Name()),
Check: testAccResourceFileSnippetUpdatedCheck(snippetFile1.Name()), Check: testAccResourceFileSnippetUpdatedCheck(snippetFile1.Name()),
}, },
// ImportState testing // ImportState testing
@ -129,13 +129,14 @@ func uploadSnippetFile(t *testing.T, file *os.File) {
sshUsername := utils.GetAnyStringEnv("PROXMOX_VE_SSH_USERNAME") sshUsername := utils.GetAnyStringEnv("PROXMOX_VE_SSH_USERNAME")
sshAgentSocket := utils.GetAnyStringEnv("SSH_AUTH_SOCK", "PROXMOX_VE_SSH_AUTH_SOCK") sshAgentSocket := utils.GetAnyStringEnv("SSH_AUTH_SOCK", "PROXMOX_VE_SSH_AUTH_SOCK")
sshPrivateKey := utils.GetAnyStringEnv("PROXMOX_VE_SSH_PRIVATE_KEY") sshPrivateKey := utils.GetAnyStringEnv("PROXMOX_VE_SSH_PRIVATE_KEY")
sshPort := utils.GetAnyIntEnv("PROXMOX_VE_ACC_NODE_SSH_PORT")
sshClient, err := ssh.NewClient( sshClient, err := ssh.NewClient(
sshUsername, "", sshAgent, sshAgentSocket, sshPrivateKey, sshUsername, "", sshAgent, sshAgentSocket, sshPrivateKey,
"", "", "", "", "", "",
&nodeResolver{ &nodeResolver{
node: ssh.ProxmoxNode{ node: ssh.ProxmoxNode{
Address: u.Hostname(), Address: u.Hostname(),
Port: 22, Port: int32(sshPort),
}, },
}, },
) )
@ -174,15 +175,15 @@ func createFile(t *testing.T, namePattern string, content string) *os.File {
return f return f
} }
func deleteSnippet(t *testing.T, fname string) { func deleteSnippet(te *testEnvironment, fname string) {
t.Helper() te.t.Helper()
err := getNodeStorageClient().DeleteDatastoreFile(context.Background(), fmt.Sprintf("snippets/%s", fname)) err := te.nodeStorageClient().DeleteDatastoreFile(context.Background(), fmt.Sprintf("snippets/%s", fname))
require.NoError(t, err) require.NoError(te.t, err)
} }
func testAccResourceFileSnippetRawCreatedConfig(t *testing.T, fname string) string { func testAccResourceFileSnippetRawCreatedConfig(te *testEnvironment, fname string) string {
t.Helper() te.t.Helper()
return fmt.Sprintf(`%s return fmt.Sprintf(`%s
resource "proxmox_virtual_environment_file" "test_raw" { resource "proxmox_virtual_environment_file" "test_raw" {
@ -196,11 +197,11 @@ test snippet
file_name = "%s" file_name = "%s"
} }
} }
`, getProviderConfig(t), accTestNodeName, fname) `, te.providerConfig, te.nodeName, fname)
} }
func testAccResourceFileCreatedConfig(t *testing.T, fname string, extra ...string) string { func testAccResourceFileCreatedConfig(te *testEnvironment, fname string, extra ...string) string {
t.Helper() te.t.Helper()
return fmt.Sprintf(`%s return fmt.Sprintf(`%s
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
@ -211,11 +212,11 @@ resource "proxmox_virtual_environment_file" "test" {
} }
%s %s
} }
`, getProviderConfig(t), accTestNodeName, strings.ReplaceAll(fname, `\`, `/`), strings.Join(extra, "\n")) `, te.providerConfig, te.nodeName, strings.ReplaceAll(fname, `\`, `/`), strings.Join(extra, "\n"))
} }
func testAccResourceFileTwoSourcesCreatedConfig(t *testing.T) string { func testAccResourceFileTwoSourcesCreatedConfig(te *testEnvironment) string {
t.Helper() te.t.Helper()
return fmt.Sprintf(`%s return fmt.Sprintf(`%s
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
@ -231,18 +232,18 @@ test snippet
path = "bar.yaml" path = "bar.yaml"
} }
} }
`, getProviderConfig(t), accTestNodeName) `, te.providerConfig, te.nodeName)
} }
func testAccResourceFileMissingSourceConfig(t *testing.T) string { func testAccResourceFileMissingSourceConfig(te *testEnvironment) string {
t.Helper() te.t.Helper()
return fmt.Sprintf(`%s return fmt.Sprintf(`%s
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
datastore_id = "local" datastore_id = "local"
node_name = "%s" node_name = "%s"
} }
`, getProviderConfig(t), accTestNodeName) `, te.providerConfig, te.nodeName)
} }
func testAccResourceFileSnippetRawCreatedCheck(fname string) resource.TestCheckFunc { func testAccResourceFileSnippetRawCreatedCheck(fname string) resource.TestCheckFunc {
@ -263,8 +264,8 @@ func testAccResourceFileCreatedCheck(ctype string, fname string) resource.TestCh
) )
} }
func testAccResourceFileSnippetUpdateConfig(t *testing.T, fname string) string { func testAccResourceFileSnippetUpdateConfig(te *testEnvironment, fname string) string {
t.Helper() te.t.Helper()
return fmt.Sprintf(`%s return fmt.Sprintf(`%s
resource "proxmox_virtual_environment_file" "test" { resource "proxmox_virtual_environment_file" "test" {
@ -274,7 +275,7 @@ resource "proxmox_virtual_environment_file" "test" {
path = "%s" path = "%s"
} }
} }
`, getProviderConfig(t), accTestNodeName, strings.ReplaceAll(fname, `\`, `/`)) `, te.providerConfig, te.nodeName, strings.ReplaceAll(fname, `\`, `/`))
} }
func testAccResourceFileSnippetUpdatedCheck(fname string) resource.TestCheckFunc { func testAccResourceFileSnippetUpdatedCheck(fname string) resource.TestCheckFunc {

View File

@ -7,7 +7,6 @@
package tests package tests
import ( import (
"context"
"fmt" "fmt"
"testing" "testing"
@ -17,7 +16,7 @@ import (
) )
func TestAccResourceLinuxBridge(t *testing.T) { func TestAccResourceLinuxBridge(t *testing.T) {
accProviders := testAccMuxProviders(context.Background(), t) te := initTestEnvironment(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())
@ -25,7 +24,7 @@ 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: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Create and Read testing // Create and Read testing
{ {
@ -39,7 +38,7 @@ func TestAccResourceLinuxBridge(t *testing.T) {
node_name = "%s" node_name = "%s"
vlan_aware = true vlan_aware = true
} }
`, ipV4cidr1, iface, accTestNodeName), `, ipV4cidr1, iface, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_network_linux_bridge.test", map[string]string{ testResourceAttributes("proxmox_virtual_environment_network_linux_bridge.test", map[string]string{
"address": ipV4cidr1, "address": ipV4cidr1,
@ -66,7 +65,7 @@ func TestAccResourceLinuxBridge(t *testing.T) {
name = "%s" name = "%s"
node_name = "%s" node_name = "%s"
vlan_aware = false vlan_aware = false
}`, ipV4cidr2, ipV6cidr, iface, accTestNodeName), }`, ipV4cidr2, ipV6cidr, iface, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_network_linux_bridge.test", map[string]string{ testResourceAttributes("proxmox_virtual_environment_network_linux_bridge.test", map[string]string{
"address": ipV4cidr2, "address": ipV4cidr2,

View File

@ -7,7 +7,6 @@
package tests package tests
import ( import (
"context"
"fmt" "fmt"
"strconv" "strconv"
"testing" "testing"
@ -21,7 +20,7 @@ const (
) )
func TestAccResourceLinuxVLAN(t *testing.T) { func TestAccResourceLinuxVLAN(t *testing.T) {
accProviders := testAccMuxProviders(context.Background(), t) te := initTestEnvironment(t)
iface := "ens18" iface := "ens18"
vlan1 := gofakeit.Number(10, 4094) vlan1 := gofakeit.Number(10, 4094)
@ -30,11 +29,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: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Create and Read testing // Create and Read testing
{ {
Config: testAccResourceLinuxVLANCreatedConfig(iface, vlan1), Config: testAccResourceLinuxVLANCreatedConfig(te, iface, vlan1),
Check: testAccResourceLinuxVLANCreatedCheck(iface, vlan1), Check: testAccResourceLinuxVLANCreatedCheck(iface, vlan1),
}, },
// ImportState testing // ImportState testing
@ -45,7 +44,7 @@ func TestAccResourceLinuxVLAN(t *testing.T) {
}, },
// Create and Read with a custom name // Create and Read with a custom name
{ {
Config: testAccResourceLinuxVLANCustomNameCreatedConfig(customName, iface, vlan2), Config: testAccResourceLinuxVLANCustomNameCreatedConfig(te, 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) {
@ -54,14 +53,14 @@ func TestAccResourceLinuxVLAN(t *testing.T) {
}, },
// Update testing // Update testing
{ {
Config: testAccResourceLinuxVLANUpdatedConfig(iface, vlan1, ipV4cidr), Config: testAccResourceLinuxVLANUpdatedConfig(te, iface, vlan1, ipV4cidr),
Check: testAccResourceLinuxVLANUpdatedCheck(iface, vlan1, ipV4cidr), Check: testAccResourceLinuxVLANUpdatedCheck(iface, vlan1, ipV4cidr),
}, },
}, },
}) })
} }
func testAccResourceLinuxVLANCreatedConfig(iface string, vlan int) string { func testAccResourceLinuxVLANCreatedConfig(te *testEnvironment, iface string, vlan int) string {
return fmt.Sprintf(` return fmt.Sprintf(`
resource "proxmox_virtual_environment_network_linux_vlan" "test" { resource "proxmox_virtual_environment_network_linux_vlan" "test" {
comment = "created by terraform" comment = "created by terraform"
@ -69,7 +68,7 @@ func testAccResourceLinuxVLANCreatedConfig(iface string, vlan int) string {
name = "%s.%d" name = "%s.%d"
node_name = "%s" node_name = "%s"
} }
`, iface, vlan, accTestNodeName) `, iface, vlan, te.nodeName)
} }
func testAccResourceLinuxVLANCreatedCheck(iface string, vlan int) resource.TestCheckFunc { func testAccResourceLinuxVLANCreatedCheck(iface string, vlan int) resource.TestCheckFunc {
@ -82,7 +81,7 @@ func testAccResourceLinuxVLANCreatedCheck(iface string, vlan int) resource.TestC
) )
} }
func testAccResourceLinuxVLANCustomNameCreatedConfig(name string, iface string, vlan int) string { func testAccResourceLinuxVLANCustomNameCreatedConfig(te *testEnvironment, name string, iface string, vlan int) string {
return fmt.Sprintf(` return fmt.Sprintf(`
resource "proxmox_virtual_environment_network_linux_vlan" "%s" { resource "proxmox_virtual_environment_network_linux_vlan" "%s" {
comment = "created by terraform" comment = "created by terraform"
@ -92,7 +91,7 @@ func testAccResourceLinuxVLANCustomNameCreatedConfig(name string, iface string,
node_name = "%s" node_name = "%s"
vlan = %d vlan = %d
} }
`, name, iface, name, accTestNodeName, vlan) `, name, iface, name, te.nodeName, vlan)
} }
func testAccResourceLinuxVLANCustomNameCreatedCheck(name string, iface string, vlan int) resource.TestCheckFunc { func testAccResourceLinuxVLANCustomNameCreatedCheck(name string, iface string, vlan int) resource.TestCheckFunc {
@ -107,7 +106,7 @@ func testAccResourceLinuxVLANCustomNameCreatedCheck(name string, iface string, v
) )
} }
func testAccResourceLinuxVLANUpdatedConfig(iface string, vlan int, ipV4cidr string) string { func testAccResourceLinuxVLANUpdatedConfig(te *testEnvironment, iface string, vlan int, ipV4cidr string) string {
return fmt.Sprintf(` return fmt.Sprintf(`
resource "proxmox_virtual_environment_network_linux_vlan" "test" { resource "proxmox_virtual_environment_network_linux_vlan" "test" {
address = "%s" address = "%s"
@ -116,7 +115,7 @@ func testAccResourceLinuxVLANUpdatedConfig(iface string, vlan int, ipV4cidr stri
name = "%s.%d" name = "%s.%d"
node_name = "%s" node_name = "%s"
} }
`, ipV4cidr, iface, vlan, accTestNodeName) `, ipV4cidr, iface, vlan, te.nodeName)
} }
func testAccResourceLinuxVLANUpdatedCheck(iface string, vlan int, ipV4cidr string) resource.TestCheckFunc { func testAccResourceLinuxVLANUpdatedCheck(iface string, vlan int, ipV4cidr string) resource.TestCheckFunc {

View File

@ -7,7 +7,6 @@
package tests package tests
import ( import (
"context"
"testing" "testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
@ -18,10 +17,10 @@ const accTestClusterOptionsName = "proxmox_virtual_environment_cluster_options.t
func TestAccResourceClusterOptions(t *testing.T) { func TestAccResourceClusterOptions(t *testing.T) {
t.Parallel() t.Parallel()
accProviders := testAccMuxProviders(context.Background(), t) te := initTestEnvironment(t)
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
// Create and Read testing // Create and Read testing
{ {

View File

@ -7,13 +7,16 @@
package tests package tests
import ( import (
"context"
"testing" "testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
) )
func TestAccResourceUser(t *testing.T) { func TestAccResourceUser(t *testing.T) {
t.Parallel()
te := initTestEnvironment(t)
tests := []struct { tests := []struct {
name string name string
steps []resource.TestStep steps []resource.TestStep
@ -27,7 +30,6 @@ func TestAccResourceUser(t *testing.T) {
expiration_date = "2034-01-01T22:00:00Z" expiration_date = "2034-01-01T22:00:00Z"
first_name = "First" first_name = "First"
last_name = "Last" last_name = "Last"
//password = "password"
user_id = "user1@pve" user_id = "user1@pve"
} }
`, `,
@ -60,12 +62,10 @@ func TestAccResourceUser(t *testing.T) {
}}}, }}},
} }
accProviders := testAccMuxProviders(context.Background(), 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: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -7,7 +7,7 @@
package tests package tests
import ( import (
"context" "fmt"
"testing" "testing"
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
@ -16,16 +16,16 @@ import (
func TestAccResourceVM(t *testing.T) { func TestAccResourceVM(t *testing.T) {
t.Parallel() t.Parallel()
providerConfig := getProviderConfig(t) te := initTestEnvironment(t)
tests := []struct { tests := []struct {
name string name string
step []resource.TestStep step []resource.TestStep
}{ }{
{"multiline description", []resource.TestStep{{ {"multiline description", []resource.TestStep{{
Config: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_vm1" { resource "proxmox_virtual_environment_vm" "test_vm1" {
node_name = "pve" node_name = "%s"
started = false started = false
description = <<-EOT description = <<-EOT
@ -33,7 +33,7 @@ func TestAccResourceVM(t *testing.T) {
description description
value value
EOT EOT
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm1", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm1", map[string]string{
"description": "my\ndescription\nvalue", "description": "my\ndescription\nvalue",
@ -41,13 +41,13 @@ func TestAccResourceVM(t *testing.T) {
), ),
}}}, }}},
{"single line description", []resource.TestStep{{ {"single line description", []resource.TestStep{{
Config: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_vm2" { resource "proxmox_virtual_environment_vm" "test_vm2" {
node_name = "pve" node_name = "%s"
started = false started = false
description = "my description value" description = "my description value"
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm2", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm2", map[string]string{
"description": "my description value", "description": "my description value",
@ -55,13 +55,13 @@ func TestAccResourceVM(t *testing.T) {
), ),
}}}, }}},
{"no description", []resource.TestStep{{ {"no description", []resource.TestStep{{
Config: ` Config: fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_vm3" { resource "proxmox_virtual_environment_vm" "test_vm3" {
node_name = "pve" node_name = "%s"
started = false started = false
description = "" description = ""
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm3", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm3", map[string]string{
"description": "", "description": "",
@ -70,26 +70,26 @@ func TestAccResourceVM(t *testing.T) {
}}}, }}},
{ {
"protection", []resource.TestStep{{ "protection", []resource.TestStep{{
Config: ` Config: fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_vm4" { resource "proxmox_virtual_environment_vm" "test_vm4" {
node_name = "pve" node_name = "%s"
started = false started = false
protection = true protection = true
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm4", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm4", map[string]string{
"protection": "true", "protection": "true",
}), }),
), ),
}, { }, {
Config: ` Config: fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_vm4" { resource "proxmox_virtual_environment_vm" "test_vm4" {
node_name = "pve" node_name = "%s"
started = false started = false
protection = false protection = false
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm4", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm4", map[string]string{
"protection": "false", "protection": "false",
@ -99,30 +99,28 @@ func TestAccResourceVM(t *testing.T) {
}, },
{ {
"update cpu block", []resource.TestStep{{ "update cpu block", []resource.TestStep{{
Config: ` Config: fmt.Sprintf(`resource "proxmox_virtual_environment_vm" "test_vm5" {
resource "proxmox_virtual_environment_vm" "test_vm5" { node_name = "%s"
node_name = "pve"
started = false started = false
cpu { cpu {
cores = 2 cores = 2
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm5", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm5", map[string]string{
"cpu.0.sockets": "1", "cpu.0.sockets": "1",
}), }),
), ),
}, { }, {
Config: ` Config: fmt.Sprintf(`resource "proxmox_virtual_environment_vm" "test_vm5" {
resource "proxmox_virtual_environment_vm" "test_vm5" { node_name = "%s"
node_name = "pve"
started = false started = false
cpu { cpu {
cores = 1 cores = 1
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm5", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm5", map[string]string{
"cpu.0.sockets": "1", "cpu.0.sockets": "1",
@ -132,30 +130,28 @@ func TestAccResourceVM(t *testing.T) {
}, },
{ {
"update memory block", []resource.TestStep{{ "update memory block", []resource.TestStep{{
Config: ` Config: fmt.Sprintf(`resource "proxmox_virtual_environment_vm" "test_vm6" {
resource "proxmox_virtual_environment_vm" "test_vm6" { node_name = "%s"
node_name = "pve"
started = false started = false
memory { memory {
dedicated = 2048 dedicated = 2048
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm6", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm6", map[string]string{
"memory.0.dedicated": "2048", "memory.0.dedicated": "2048",
}), }),
), ),
}, { }, {
Config: ` Config: fmt.Sprintf(`resource "proxmox_virtual_environment_vm" "test_vm6" {
resource "proxmox_virtual_environment_vm" "test_vm6" { node_name = "%s"
node_name = "pve"
started = false started = false
memory { memory {
dedicated = 1024 dedicated = 1024
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm6", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm6", map[string]string{
"memory.0.dedicated": "1024", "memory.0.dedicated": "1024",
@ -165,14 +161,12 @@ func TestAccResourceVM(t *testing.T) {
}, },
} }
accProviders := testAccMuxProviders(context.Background(), 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) {
t.Parallel() t.Parallel()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: tt.step, Steps: tt.step,
}) })
}) })
@ -180,18 +174,18 @@ func TestAccResourceVM(t *testing.T) {
} }
func TestAccResourceVMInitialization(t *testing.T) { func TestAccResourceVMInitialization(t *testing.T) {
providerConfig := getProviderConfig(t) te := initTestEnvironment(t)
tests := []struct { tests := []struct {
name string name string
step []resource.TestStep step []resource.TestStep
}{ }{
{"initialization works with cloud-init config provided over SCSI interface", []resource.TestStep{{ {"initialization works with cloud-init config provided over SCSI interface", []resource.TestStep{{
Config: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
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 = "pve" node_name = "%[1]s"
source_raw { source_raw {
data = <<EOF data = <<EOF
#cloud-config #cloud-config
@ -206,7 +200,7 @@ EOF
} }
resource "proxmox_virtual_environment_vm" "test_vm_network1" { resource "proxmox_virtual_environment_vm" "test_vm_network1" {
node_name = "pve" node_name = "%[1]s"
started = true started = true
agent { agent {
enabled = true enabled = true
@ -244,19 +238,17 @@ EOF
resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" { resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" {
content_type = "iso" content_type = "iso"
datastore_id = "local" datastore_id = "local"
node_name = "pve" node_name = "%[1]s"
url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
overwrite_unmanaged = true overwrite_unmanaged = true
}`, }`, te.nodeName),
}}}, }}},
} }
accProviders := testAccMuxProviders(context.Background(), 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: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: tt.step, Steps: tt.step,
}) })
}) })
@ -264,18 +256,18 @@ EOF
} }
func TestAccResourceVMNetwork(t *testing.T) { func TestAccResourceVMNetwork(t *testing.T) {
providerConfig := getProviderConfig(t) te := initTestEnvironment(t)
tests := []struct { tests := []struct {
name string name string
step []resource.TestStep step []resource.TestStep
}{ }{
{"network interfaces", []resource.TestStep{{ {"network interfaces", []resource.TestStep{{
Config: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
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 = "pve" node_name = "%[1]s"
source_raw { source_raw {
data = <<EOF data = <<EOF
#cloud-config #cloud-config
@ -290,7 +282,7 @@ EOF
} }
resource "proxmox_virtual_environment_vm" "test_vm_network1" { resource "proxmox_virtual_environment_vm" "test_vm_network1" {
node_name = "pve" node_name = "%[1]s"
started = true started = true
agent { agent {
enabled = true enabled = true
@ -326,10 +318,10 @@ EOF
resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" { resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" {
content_type = "iso" content_type = "iso"
datastore_id = "local" datastore_id = "local"
node_name = "pve" node_name = "%[1]s"
url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
overwrite_unmanaged = true overwrite_unmanaged = true
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network1", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network1", map[string]string{
"ipv4_addresses.#": "2", "ipv4_addresses.#": "2",
@ -340,15 +332,15 @@ EOF
), ),
}}}, }}},
{"network device disconnected", []resource.TestStep{{ {"network device disconnected", []resource.TestStep{{
Config: ` Config: te.providerConfig + fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_vm_network2" { resource "proxmox_virtual_environment_vm" "test_vm_network2" {
node_name = "pve" node_name = "%s"
started = false started = false
network_device { network_device {
bridge = "vmbr0" bridge = "vmbr0"
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network2", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network2", map[string]string{
"network_device.0.bridge": "vmbr0", "network_device.0.bridge": "vmbr0",
@ -356,16 +348,16 @@ EOF
}), }),
), ),
}, { }, {
Config: ` Config: te.providerConfig + fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_vm_network2" { resource "proxmox_virtual_environment_vm" "test_vm_network2" {
node_name = "pve" node_name = "%s"
started = false started = false
network_device { network_device {
bridge = "vmbr0" bridge = "vmbr0"
disconnected = true disconnected = true
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network2", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_vm_network2", map[string]string{
"network_device.0.bridge": "vmbr0", "network_device.0.bridge": "vmbr0",
@ -375,14 +367,12 @@ EOF
}}}, }}},
} }
accProviders := testAccMuxProviders(context.Background(), 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) {
t.Parallel() t.Parallel()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: tt.step, Steps: tt.step,
}) })
}) })
@ -392,7 +382,7 @@ EOF
func TestAccResourceVMDisks(t *testing.T) { func TestAccResourceVMDisks(t *testing.T) {
t.Parallel() t.Parallel()
providerConfig := getProviderConfig(t) te := initTestEnvironment(t)
tests := []struct { tests := []struct {
name string name string
@ -400,9 +390,9 @@ 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: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_disk1" { resource "proxmox_virtual_environment_vm" "test_disk1" {
node_name = "pve" node_name = "%s"
started = false started = false
name = "test-disk1" name = "test-disk1"
@ -413,7 +403,7 @@ func TestAccResourceVMDisks(t *testing.T) {
interface = "virtio0" interface = "virtio0"
size = 8 size = 8
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{
"disk.0.aio": "io_uring", "disk.0.aio": "io_uring",
@ -433,9 +423,9 @@ func TestAccResourceVMDisks(t *testing.T) {
), ),
}, },
{ {
Config: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_disk1" { resource "proxmox_virtual_environment_vm" "test_disk1" {
node_name = "pve" node_name = "%s"
started = false started = false
name = "test-disk1" name = "test-disk1"
@ -454,7 +444,7 @@ func TestAccResourceVMDisks(t *testing.T) {
iops_write_burstable = 800 iops_write_burstable = 800
} }
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_disk1", map[string]string{
"disk.0.aio": "native", "disk.0.aio": "native",
@ -479,16 +469,16 @@ func TestAccResourceVMDisks(t *testing.T) {
}, },
}}, }},
{"create disk from an image", []resource.TestStep{{ {"create disk from an image", []resource.TestStep{{
Config: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
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"
node_name = "pve" node_name = "%[1]s"
url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
overwrite_unmanaged = true overwrite_unmanaged = true
} }
resource "proxmox_virtual_environment_vm" "test_disk2" { resource "proxmox_virtual_environment_vm" "test_disk2" {
node_name = "pve" node_name = "%[1]s"
started = false started = false
name = "test-disk2" name = "test-disk2"
disk { disk {
@ -499,7 +489,7 @@ func TestAccResourceVMDisks(t *testing.T) {
discard = "on" discard = "on"
size = 20 size = 20
} }
}`, }`, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_disk2", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_disk2", map[string]string{
"disk.0.cache": "none", "disk.0.cache": "none",
@ -516,9 +506,9 @@ func TestAccResourceVMDisks(t *testing.T) {
}}}, }}},
{"clone default disk without overrides", []resource.TestStep{ {"clone default disk without overrides", []resource.TestStep{
{ {
Config: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_disk3_template" { resource "proxmox_virtual_environment_vm" "test_disk3_template" {
node_name = "pve" node_name = "%[1]s"
started = false started = false
name = "test-disk3-template" name = "test-disk3-template"
template = "true" template = "true"
@ -531,7 +521,7 @@ func TestAccResourceVMDisks(t *testing.T) {
} }
} }
resource "proxmox_virtual_environment_vm" "test_disk3" { resource "proxmox_virtual_environment_vm" "test_disk3" {
node_name = "pve" node_name = "%[1]s"
started = false started = false
name = "test-disk3" name = "test-disk3"
@ -539,7 +529,7 @@ func TestAccResourceVMDisks(t *testing.T) {
vm_id = proxmox_virtual_environment_vm.test_disk3_template.id vm_id = proxmox_virtual_environment_vm.test_disk3_template.id
} }
} }
`, `, te.nodeName),
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"),
@ -556,9 +546,9 @@ 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: providerConfig + ` Config: te.providerConfig + fmt.Sprintf(`
resource "proxmox_virtual_environment_vm" "test_disk3_template" { resource "proxmox_virtual_environment_vm" "test_disk3_template" {
node_name = "pve" node_name = "%[1]s"
started = false started = false
name = "test-disk3-template" name = "test-disk3-template"
template = "true" template = "true"
@ -574,7 +564,7 @@ func TestAccResourceVMDisks(t *testing.T) {
} }
} }
resource "proxmox_virtual_environment_vm" "test_disk3" { resource "proxmox_virtual_environment_vm" "test_disk3" {
node_name = "pve" node_name = "%[1]s"
started = false started = false
name = "test-disk3" name = "test-disk3"
@ -587,7 +577,7 @@ func TestAccResourceVMDisks(t *testing.T) {
//size = 10 //size = 10
} }
} }
`, `, te.nodeName),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{ testResourceAttributes("proxmox_virtual_environment_vm.test_disk3", map[string]string{
"disk.0.datastore_id": "local-lvm", "disk.0.datastore_id": "local-lvm",
@ -608,14 +598,12 @@ func TestAccResourceVMDisks(t *testing.T) {
}}, }},
} }
accProviders := testAccMuxProviders(context.Background(), 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) {
t.Parallel() t.Parallel()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders, ProtoV6ProviderFactories: te.accProviders,
Steps: tt.steps, Steps: tt.steps,
}) })
}) })

View File

@ -0,0 +1,157 @@
package tests
import (
"context"
"fmt"
"net/url"
"sync"
"testing"
"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-mux/tf5to6server"
"github.com/hashicorp/terraform-plugin-mux/tf6muxserver"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/stretchr/testify/require"
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/nodes"
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage"
"github.com/bpg/terraform-provider-proxmox/utils"
)
const (
accTestStorageName = "local"
)
type testEnvironment struct {
t *testing.T
providerConfig string
accProviders map[string]func() (tfprotov6.ProviderServer, error)
nodeName string
once sync.Once
nc *nodes.Client
}
func initTestEnvironment(t *testing.T) *testEnvironment {
t.Helper()
nodeName := utils.GetAnyStringEnv("PROXMOX_VE_ACC_NODE_NAME")
if nodeName == "" {
nodeName = "pve"
}
nodeAddress := utils.GetAnyStringEnv("PROXMOX_VE_ACC_NODE_SSH_ADDRESS")
if nodeAddress == "" {
endpoint := utils.GetAnyStringEnv("PROXMOX_VE_ENDPOINT")
u, err := url.Parse(endpoint)
require.NoError(t, err)
nodeAddress = u.Hostname()
}
nodePort := utils.GetAnyStringEnv("PROXMOX_VE_ACC_NODE_SSH_PORT")
if nodePort == "" {
nodePort = "22"
}
pc := fmt.Sprintf(`
provider "proxmox" {
ssh {
node {
name = "%s"
address = "%s"
port = %s
}
}
}
`, nodeName, nodeAddress, nodePort)
return &testEnvironment{
t: t,
providerConfig: pc,
accProviders: muxProviders(t),
nodeName: nodeName,
}
}
func (e *testEnvironment) nodeClient() *nodes.Client {
if e.nc == nil {
e.once.Do(
func() {
username := utils.GetAnyStringEnv("PROXMOX_VE_USERNAME")
password := utils.GetAnyStringEnv("PROXMOX_VE_PASSWORD")
endpoint := utils.GetAnyStringEnv("PROXMOX_VE_ENDPOINT")
apiToken := utils.GetAnyStringEnv("PROXMOX_VE_API_TOKEN")
creds, err := api.NewCredentials(username, password, "", apiToken)
if err != nil {
panic(err)
}
conn, err := api.NewConnection(endpoint, true, "")
if err != nil {
panic(err)
}
client, err := api.NewClient(creds, conn)
if err != nil {
panic(err)
}
e.nc = &nodes.Client{Client: client, NodeName: e.nodeName}
})
}
return e.nc
}
func (e *testEnvironment) nodeStorageClient() *storage.Client {
nodesClient := e.nodeClient()
return &storage.Client{Client: nodesClient, StorageName: accTestStorageName}
}
// testAccMuxProviders returns a map of mux servers for the acceptance tests.
func muxProviders(t *testing.T) map[string]func() (tfprotov6.ProviderServer, error) {
t.Helper()
ctx := context.Background()
// Init sdkV2 provider
sdkV2Provider, err := tf5to6server.UpgradeServer(
ctx,
func() tfprotov5.ProviderServer {
return schema.NewGRPCProviderServer(
sdkV2provider.ProxmoxVirtualEnvironment(),
)
},
)
require.NoError(t, err)
// Init framework provider
frameworkProvider := fwprovider.New("test")()
providers := []func() tfprotov6.ProviderServer{
providerserver.NewProtocol6(frameworkProvider),
func() tfprotov6.ProviderServer {
return sdkV2Provider
},
}
// Init mux servers
muxServers := map[string]func() (tfprotov6.ProviderServer, error){
"proxmox": func() (tfprotov6.ProviderServer, error) {
muxServer, e := tf6muxserver.NewMuxServer(ctx, providers...)
if e != nil {
return nil, fmt.Errorf("failed to create mux server: %w", e)
}
return muxServer, nil
},
}
return muxServers
}

View File

@ -7,117 +7,13 @@
package tests package tests
import ( import (
"context"
"fmt" "fmt"
"net/url"
"regexp" "regexp"
"sync"
"testing"
"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov5"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-mux/tf5to6server"
"github.com/hashicorp/terraform-plugin-mux/tf6muxserver"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/stretchr/testify/require"
"github.com/bpg/terraform-provider-proxmox/fwprovider"
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes"
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage"
sdkV2provider "github.com/bpg/terraform-provider-proxmox/proxmoxtf/provider"
"github.com/bpg/terraform-provider-proxmox/utils"
) )
const (
accTestNodeName = "pve"
accTestStorageName = "local"
)
// testAccMuxProviders returns a map of mux servers for the acceptance tests.
func testAccMuxProviders(ctx context.Context, t *testing.T) map[string]func() (tfprotov6.ProviderServer, error) {
t.Helper()
// Init sdkV2 provider
sdkV2Provider, err := tf5to6server.UpgradeServer(
ctx,
func() tfprotov5.ProviderServer {
return schema.NewGRPCProviderServer(
sdkV2provider.ProxmoxVirtualEnvironment(),
)
},
)
require.NoError(t, err)
// Init framework provider
frameworkProvider := fwprovider.New("test")()
providers := []func() tfprotov6.ProviderServer{
providerserver.NewProtocol6(frameworkProvider),
func() tfprotov6.ProviderServer {
return sdkV2Provider
},
}
// Init mux servers
muxServers := map[string]func() (tfprotov6.ProviderServer, error){
"proxmox": func() (tfprotov6.ProviderServer, error) {
muxServer, e := tf6muxserver.NewMuxServer(ctx, providers...)
if e != nil {
return nil, fmt.Errorf("failed to create mux server: %w", e)
}
return muxServer, nil
},
}
return muxServers
}
//nolint:gochecknoglobals
var (
once sync.Once
nodesClient *nodes.Client
)
func getNodesClient() *nodes.Client {
if nodesClient == nil {
once.Do(
func() {
username := utils.GetAnyStringEnv("PROXMOX_VE_USERNAME")
password := utils.GetAnyStringEnv("PROXMOX_VE_PASSWORD")
endpoint := utils.GetAnyStringEnv("PROXMOX_VE_ENDPOINT")
apiToken := utils.GetAnyStringEnv("PROXMOX_VE_API_TOKEN")
creds, err := api.NewCredentials(username, password, "", apiToken)
if err != nil {
panic(err)
}
conn, err := api.NewConnection(endpoint, true, "")
if err != nil {
panic(err)
}
client, err := api.NewClient(creds, conn)
if err != nil {
panic(err)
}
nodesClient = &nodes.Client{Client: client, NodeName: accTestNodeName}
})
}
return nodesClient
}
func getNodeStorageClient() *storage.Client {
nodesClient := getNodesClient()
return &storage.Client{Client: nodesClient, StorageName: accTestStorageName}
}
func testResourceAttributes(res string, attrs map[string]string) resource.TestCheckFunc { func testResourceAttributes(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 {
@ -170,21 +66,3 @@ func testResourceAttributesSet(res string, attrs []string) resource.TestCheckFun
return nil return nil
} }
} }
func getProviderConfig(t *testing.T) string {
t.Helper()
endpoint := utils.GetAnyStringEnv("PROXMOX_VE_ENDPOINT")
u, err := url.Parse(endpoint)
require.NoError(t, err)
return fmt.Sprintf(`
provider "proxmox" {
ssh {
node {
name = "%s"
address = "%s"
}
}
}`, accTestNodeName, u.Hostname())
}

View File

@ -23,7 +23,7 @@ func (c *Client) GetQueryURLMetadata(
err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("query-url-metadata"), d, resBody) err := c.DoRequest(ctx, http.MethodGet, c.ExpandPath("query-url-metadata"), d, resBody)
if err != nil { if err != nil {
return nil, fmt.Errorf("error retrieving Query URL metadata configuration: %w", err) return nil, fmt.Errorf("error retrieving URL metadata for %+v: %w", d.URL, err)
} }
if resBody.Data == nil { if resBody.Data == nil {

View File

@ -6,7 +6,10 @@
package utils package utils
import "os" import (
"os"
"strconv"
)
// GetAnyStringEnv returns the first non-empty string value from the environment variables. // GetAnyStringEnv returns the first non-empty string value from the environment variables.
func GetAnyStringEnv(ks ...string) string { func GetAnyStringEnv(ks ...string) string {
@ -32,3 +35,16 @@ func GetAnyBoolEnv(ks ...string) bool {
return val == "true" || val == "1" return val == "true" || val == "1"
} }
// GetAnyIntEnv returns the first non-empty integer value from the environment variables.
func GetAnyIntEnv(ks ...string) int {
for _, k := range ks {
if v := os.Getenv(k); v != "" {
if i, err := strconv.Atoi(v); err == nil {
return i
}
}
}
return 0
}