diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 4364526c..59ebb402 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -34,6 +34,9 @@ jobs: if: steps.filter.outputs.go == 'true' with: go-version-file: "go.mod" + cache-dependency-path: | + go.sum + tools/go.sum - name: Lint code if: steps.filter.outputs.go == 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c96c8247..3345eb4a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,6 +29,9 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: "go.mod" + cache-dependency-path: | + go.sum + tools/go.sum - name: Get dependencies if: steps.filter.outputs.go == 'true' @@ -60,6 +63,9 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: "go.mod" + cache-dependency-path: | + go.sum + tools/go.sum - name: Get dependencies if: steps.filter.outputs.go == 'true' @@ -69,3 +75,6 @@ jobs: if: steps.filter.outputs.go == 'true' timeout-minutes: 10 run: go test -v -cover ./... + + - name: Check for uncommitted changes in generated docs + run: make docs && git diff --exit-code diff --git a/docs/guides/cloud-image.md b/docs/guides/cloud-image.md index f1ca7263..5c5d410d 100644 --- a/docs/guides/cloud-image.md +++ b/docs/guides/cloud-image.md @@ -41,7 +41,7 @@ resource "proxmox_virtual_environment_download_file" "centos_cloud_image" { content_type = "iso" datastore_id = "local" node_name = "pve" - url = "https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-20231113.0.x86_64.qcow2" + url = "https://cloud.centos.org/centos/8-stream/x86_64/images/CentOS-Stream-GenericCloud-8-latest.x86_64.qcow2" file_name = "centos8.img" } ``` @@ -76,7 +76,6 @@ resource "proxmox_virtual_environment_download_file" "ubuntu_cloud_image" { datastore_id = "local" node_name = "pve" url = "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" - } ``` diff --git a/docs/resources/virtual_environment_download_file.md b/docs/resources/virtual_environment_download_file.md index 464816e7..61de4cec 100644 --- a/docs/resources/virtual_environment_download_file.md +++ b/docs/resources/virtual_environment_download_file.md @@ -82,6 +82,7 @@ resource "proxmox_virtual_environment_download_file" "latest_ubuntu_22_jammy_lxc - `decompression_algorithm` (String) Decompress the downloaded file using the specified compression algorithm. Must be one of `gz` | `lzo` | `zst`. - `file_name` (String) The file name. If not provided, it is calculated using `url`. PVE will raise 'wrong file extension' error for some popular extensions file `.raw` or `.qcow2`. Workaround is to use e.g. `.img` instead. - `overwrite` (Boolean) If `true` and size of uploaded file is different, than size from `url` Content-Length header, file will be downloaded again. If `false`, there will be no checks. +- `overwrite_unmanaged` (Boolean) If `true` and a file with the same name already exists in the datastore, it will be deleted and the new file will be downloaded. If `false` and the file already exists, an error will be returned. - `upload_timeout` (Number) The file download timeout seconds. Default is 600 (10min). - `verify` (Boolean) By default `true`. If `false`, no SSL/TLS certificates will be verified. diff --git a/example/resource_virtual_environment_download_file.tf b/example/resource_virtual_environment_download_file.tf index ba592402..d91d7ef9 100644 --- a/example/resource_virtual_environment_download_file.tf +++ b/example/resource_virtual_environment_download_file.tf @@ -1,20 +1,22 @@ ## Debian and ubuntu image download resource "proxmox_virtual_environment_download_file" "release_20231211_ubuntu_22_jammy_lxc_img" { - content_type = "vztmpl" - datastore_id = "local" - node_name = "pve" - url = "https://cloud-images.ubuntu.com/releases/22.04/release-20231211/ubuntu-22.04-server-cloudimg-amd64-root.tar.xz" - checksum = "c9997dcfea5d826fd04871f960c513665f2e87dd7450bba99f68a97e60e4586e" - checksum_algorithm = "sha256" - upload_timeout = 4444 + content_type = "vztmpl" + datastore_id = "local" + node_name = "pve" + url = "https://cloud-images.ubuntu.com/releases/22.04/release-20231211/ubuntu-22.04-server-cloudimg-amd64-root.tar.xz" + checksum = "c9997dcfea5d826fd04871f960c513665f2e87dd7450bba99f68a97e60e4586e" + checksum_algorithm = "sha256" + upload_timeout = 4444 + overwrite_unmanaged = true } resource "proxmox_virtual_environment_download_file" "latest_debian_12_bookworm_qcow2_img" { - content_type = "iso" - datastore_id = "local" - file_name = "debian-12-generic-amd64.img" - node_name = "pve" - url = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2" - overwrite = true + content_type = "iso" + datastore_id = "local" + file_name = "debian-12-generic-amd64.img" + node_name = "pve" + url = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2" + overwrite = true + overwrite_unmanaged = true } diff --git a/fwprovider/resource_download_file.go b/fwprovider/resource_download_file.go index af700a27..a4dfe2b6 100644 --- a/fwprovider/resource_download_file.go +++ b/fwprovider/resource_download_file.go @@ -13,7 +13,6 @@ import ( "strconv" "strings" - "github.com/bpg/terraform-provider-proxmox/fwprovider/structure" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -26,6 +25,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/bpg/terraform-provider-proxmox/fwprovider/structure" + "github.com/bpg/terraform-provider-proxmox/proxmox" "github.com/bpg/terraform-provider-proxmox/proxmox/nodes" "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage" @@ -33,9 +34,9 @@ import ( ) var ( - _ resource.Resource = &downloadFileResource{} - _ resource.ResourceWithConfigure = &downloadFileResource{} - httpRe = regexp.MustCompile(`https?://.*`) + _ resource.Resource = &downloadFileResource{} + _ resource.ResourceWithConfigure = &downloadFileResource{} + httpRegex = regexp.MustCompile(`https?://.*`) ) func sizeRequiresReplace() planmodifier.Int64 { @@ -54,7 +55,7 @@ func (r sizeRequiresReplaceModifier) PlanModifyInt64( return } - // // Do not replace on resource destroy. + // Do not replace on resource destroy. if req.Plan.Raw.IsNull() { return } @@ -157,9 +158,10 @@ type downloadFileModel struct { ChecksumAlgorithm types.String `tfsdk:"checksum_algorithm"` Verify types.Bool `tfsdk:"verify"` Overwrite types.Bool `tfsdk:"overwrite"` + OverwriteUnmanaged types.Bool `tfsdk:"overwrite_unmanaged"` } -// NewDownloadFileResource manages files downloaded using proxmomx API. +// NewDownloadFileResource manages files downloaded using Proxmox API. func NewDownloadFileResource() resource.Resource { return &downloadFileResource{} } @@ -247,7 +249,7 @@ func (r *downloadFileResource) Schema( Description: "The URL to download the file from. Format `https?://.*`.", Required: true, Validators: []validator.String{ - stringvalidator.RegexMatches(httpRe, "Must match http url regex"), + stringvalidator.RegexMatches(httpRegex, "Must match http url regex"), }, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), @@ -311,6 +313,14 @@ func (r *downloadFileResource) Schema( Computed: true, Default: booldefault.StaticBool(true), }, + "overwrite_unmanaged": schema.BoolAttribute{ + Description: "If `true` and a file with the same name already exists in the datastore, " + + "it will be deleted and the new file will be downloaded. If `false` and the file already exists, " + + "an error will be returned.", + Optional: true, + Computed: true, + Default: booldefault.StaticBool(false), + }, }, } } @@ -390,24 +400,36 @@ func (r *downloadFileResource) Create( plan.UploadTimeout.ValueInt64(), ) + if isErrFileAlreadyExists(err) && plan.OverwriteUnmanaged.ValueBool() { + fileID := plan.Content.ValueString() + "/" + plan.FileName.ValueString() + + err = storageClient.DeleteDatastoreFile(ctx, fileID) + if err != nil { + resp.Diagnostics.AddError("Error deleting file from datastore", + fmt.Sprintf("Could not delete file '%s', unexpected error: %s", fileID, err.Error()), + ) + } + + err = storageClient.DownloadFileByURL( + ctx, + &downloadFileReq, + plan.UploadTimeout.ValueInt64(), + ) + } + if err != nil { - if strings.Contains(err.Error(), "refusing to override existing file") { + if isErrFileAlreadyExists(err) { resp.Diagnostics.AddError( - "File already exists in a datastore, it was created outside of Terraform "+ + "File already exists in the datastore, it was created outside of Terraform "+ "or is managed by another resource.", - fmt.Sprintf( - "File already exists in a datastore: `%s`, "+ - "error: %s", - plan.FileName.ValueString(), - err.Error(), + fmt.Sprintf("File already exists in the datastore: '%s', error: %s", + plan.FileName.ValueString(), err.Error(), ), ) } else { resp.Diagnostics.AddError( - "Error creating Download File interface", - fmt.Sprintf( - "Could not DownloadFileByURL: `%s`, "+ - "unexpected error: %s", + "Error downloading file from url", + fmt.Sprintf("Could not download file '%s', unexpected error: %s", plan.FileName.ValueString(), err.Error(), ), @@ -607,3 +629,11 @@ func (r *downloadFileResource) Delete( } } } + +func isErrFileAlreadyExists(err error) bool { + if err == nil { + return false + } + + return strings.Contains(err.Error(), "refusing to override existing file") +} diff --git a/fwprovider/tests/resource_download_file_test.go b/fwprovider/tests/resource_download_file_test.go index 937c1dfd..b43b9d8a 100644 --- a/fwprovider/tests/resource_download_file_test.go +++ b/fwprovider/tests/resource_download_file_test.go @@ -12,122 +12,164 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/stretchr/testify/require" + + "github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage" + "github.com/bpg/terraform-provider-proxmox/proxmox/types" ) const ( - accTestDownloadIsoFileName = "proxmox_virtual_environment_download_file.iso_image" - accTestDownloadQcow2FileName = "proxmox_virtual_environment_download_file.qcow2_image" + fakeFileISO = "https://cdn.githubraw.com/rafsaf/a4b19ea5e3485f8da6ca4acf46d09650/raw/d340ec3ddcef9b907ede02f64b5d3f694da5d081/fake_file.iso" + fakeFileQCOW2 = "https://cdn.githubraw.com/rafsaf/036eece601975a3ad632a77fc2809046/raw/10500012fca9b4425b50de67a7258a12cba0c076/fake_file.qcow2" ) //nolint:paralleltest func TestAccResourceDownloadFile(t *testing.T) { + tests := []struct { + name string + steps []resource.TestStep + }{ + {"download iso file", []resource.TestStep{{ + Config: fmt.Sprintf(` + resource "proxmox_virtual_environment_download_file" "iso_image" { + content_type = "iso" + node_name = "%s" + datastore_id = "%s" + url = "%s" + } + `, accTestNodeName, accTestStorageName, fakeFileISO), + Check: resource.ComposeTestCheckFunc( + testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{ + "id": "local:iso/fake_file.iso", + "node_name": accTestNodeName, + "datastore_id": accTestStorageName, + "url": fakeFileISO, + "file_name": "fake_file.iso", + "upload_timeout": "600", + "size": "3", + "verify": "true", + }), + testNoResourceAttributes("proxmox_virtual_environment_download_file.iso_image", []string{ + "checksum", + "checksum_algorithm", + "decompression_algorithm", + }), + ), + }}}, + {"download qcow2 file", []resource.TestStep{{ + Config: fmt.Sprintf(` + resource "proxmox_virtual_environment_download_file" "qcow2_image" { + content_type = "iso" + node_name = "%s" + datastore_id = "%s" + file_name = "fake_qcow2_file.img" + url = "%s" + checksum = "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6" + checksum_algorithm = "sha256" + } + `, accTestNodeName, accTestStorageName, fakeFileQCOW2), + Check: resource.ComposeTestCheckFunc( + testResourceAttributes("proxmox_virtual_environment_download_file.qcow2_image", map[string]string{ + "id": "local:iso/fake_qcow2_file.img", + "content_type": "iso", + "node_name": accTestNodeName, + "datastore_id": accTestStorageName, + "url": fakeFileQCOW2, + "file_name": "fake_qcow2_file.img", + "upload_timeout": "600", + "size": "3", + "verify": "true", + "checksum": "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6", + "checksum_algorithm": "sha256", + }), + testNoResourceAttributes("proxmox_virtual_environment_download_file.qcow2_image", []string{ + "decompression_algorithm", + }), + ), + }}}, + {"update file", []resource.TestStep{{ + Config: fmt.Sprintf(` + resource "proxmox_virtual_environment_download_file" "iso_image" { + content_type = "iso" + node_name = "%s" + datastore_id = "%s" + file_name = "fake_iso_file.img" + url = "%s" + upload_timeout = 10000 + } + `, accTestNodeName, accTestStorageName, fakeFileISO), + Check: resource.ComposeTestCheckFunc( + testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{ + "id": "local:iso/fake_iso_file.img", + "content_type": "iso", + "node_name": accTestNodeName, + "datastore_id": accTestStorageName, + "url": fakeFileISO, + "file_name": "fake_iso_file.img", + "upload_timeout": "10000", + "size": "3", + "verify": "true", + }), + testNoResourceAttributes("proxmox_virtual_environment_download_file.iso_image", []string{ + "checksum", + "checksum_algorithm", + "decompression_algorithm", + }), + ), + }}}, + {"override unmanaged file", []resource.TestStep{{ + PreConfig: func() { + err := getNodeStorageClient().DownloadFileByURL(context.Background(), &storage.DownloadURLPostRequestBody{ + Content: types.StrPtr("iso"), + FileName: types.StrPtr("fake_file.iso"), + Node: types.StrPtr(accTestNodeName), + Storage: types.StrPtr(accTestStorageName), + URL: types.StrPtr(fakeFileISO), + }, 600) + require.NoError(t, err) + t.Cleanup(func() { + err := getNodeStorageClient().DeleteDatastoreFile(context.Background(), "iso/fake_file.iso") + require.NoError(t, err) + }) + }, + Config: fmt.Sprintf(` + resource "proxmox_virtual_environment_download_file" "iso_image" { + content_type = "iso" + node_name = "%s" + datastore_id = "%s" + url = "%s" + overwrite_unmanaged = true + } + `, accTestNodeName, accTestStorageName, fakeFileISO), + Check: resource.ComposeTestCheckFunc( + testResourceAttributes("proxmox_virtual_environment_download_file.iso_image", map[string]string{ + "id": "local:iso/fake_file.iso", + "content_type": "iso", + "node_name": accTestNodeName, + "datastore_id": accTestStorageName, + "url": fakeFileISO, + "file_name": "fake_file.iso", + "size": "3", + "verify": "true", + }), + testNoResourceAttributes("proxmox_virtual_environment_download_file.iso_image", []string{ + "checksum", + "checksum_algorithm", + "decompression_algorithm", + }), + ), + }}}, + } + accProviders := testAccMuxProviders(context.Background(), t) - resource.Test(t, resource.TestCase{ - ProtoV6ProviderFactories: accProviders, - Steps: []resource.TestStep{ - // Create and Read testing - { - Config: testAccResourceDownloadIsoFileCreatedConfig(), - Check: testAccResourceDownloadIsoFileCreatedCheck(), - }, - { - Config: testAccResourceDownloadQcow2FileCreatedConfig(), - Check: testAccResourceDownloadQcow2FileCreatedCheck(), - }, - // Update testing - { - Config: testAccResourceDownloadIsoFileUpdatedConfig(), - Check: testAccResourceDownloadIsoFileUpdatedCheck(), - }, - }, - }) -} - -func testAccResourceDownloadIsoFileCreatedConfig() string { - return fmt.Sprintf(` - resource "proxmox_virtual_environment_download_file" "iso_image" { - content_type = "iso" - node_name = "%s" - datastore_id = "%s" - url = "https://cdn.githubraw.com/rafsaf/a4b19ea5e3485f8da6ca4acf46d09650/raw/d340ec3ddcef9b907ede02f64b5d3f694da5d081/fake_file.iso" - } - `, accTestNodeName, accTestStorageName) -} - -func testAccResourceDownloadQcow2FileCreatedConfig() string { - return fmt.Sprintf(` - resource "proxmox_virtual_environment_download_file" "qcow2_image" { - content_type = "iso" - node_name = "%s" - datastore_id = "%s" - file_name = "fake_qcow2_file.img" - url = "https://cdn.githubraw.com/rafsaf/036eece601975a3ad632a77fc2809046/raw/10500012fca9b4425b50de67a7258a12cba0c076/fake_file.qcow2" - checksum = "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6" - checksum_algorithm = "sha256" - } - `, accTestNodeName, accTestStorageName) -} - -func testAccResourceDownloadIsoFileCreatedCheck() resource.TestCheckFunc { - return resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "id", "local:iso/fake_file.iso"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "node_name", accTestNodeName), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "datastore_id", accTestStorageName), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "url", "https://cdn.githubraw.com/rafsaf/a4b19ea5e3485f8da6ca4acf46d09650/raw/d340ec3ddcef9b907ede02f64b5d3f694da5d081/fake_file.iso"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "file_name", "fake_file.iso"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "upload_timeout", "600"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "size", "3"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "verify", "true"), - resource.TestCheckNoResourceAttr(accTestDownloadIsoFileName, "checksum"), - resource.TestCheckNoResourceAttr(accTestDownloadIsoFileName, "checksum_algorithm"), - resource.TestCheckNoResourceAttr(accTestDownloadIsoFileName, "decompression_algorithm"), - ) -} - -func testAccResourceDownloadQcow2FileCreatedCheck() resource.TestCheckFunc { - return resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "id", "local:iso/fake_qcow2_file.img"), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "content_type", "iso"), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "node_name", accTestNodeName), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "datastore_id", accTestStorageName), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "url", "https://cdn.githubraw.com/rafsaf/036eece601975a3ad632a77fc2809046/raw/10500012fca9b4425b50de67a7258a12cba0c076/fake_file.qcow2"), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "file_name", "fake_qcow2_file.img"), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "upload_timeout", "600"), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "size", "3"), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "verify", "true"), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "checksum", "688787d8ff144c502c7f5cffaafe2cc588d86079f9de88304c26b0cb99ce91c6"), - resource.TestCheckResourceAttr(accTestDownloadQcow2FileName, "checksum_algorithm", "sha256"), - resource.TestCheckNoResourceAttr(accTestDownloadQcow2FileName, "decompression_algorithm"), - ) -} - -func testAccResourceDownloadIsoFileUpdatedConfig() string { - return fmt.Sprintf(` - resource "proxmox_virtual_environment_download_file" "iso_image" { - content_type = "iso" - node_name = "%s" - datastore_id = "%s" - file_name = "fake_iso_file.img" - url = "https://cdn.githubraw.com/rafsaf/a4b19ea5e3485f8da6ca4acf46d09650/raw/d340ec3ddcef9b907ede02f64b5d3f694da5d081/fake_file.iso" - upload_timeout = 10000 - } - `, accTestNodeName, accTestStorageName) -} - -func testAccResourceDownloadIsoFileUpdatedCheck() resource.TestCheckFunc { - return resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "id", "local:iso/fake_iso_file.img"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "content_type", "iso"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "node_name", accTestNodeName), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "datastore_id", accTestStorageName), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "url", "https://cdn.githubraw.com/rafsaf/a4b19ea5e3485f8da6ca4acf46d09650/raw/d340ec3ddcef9b907ede02f64b5d3f694da5d081/fake_file.iso"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "file_name", "fake_iso_file.img"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "upload_timeout", "10000"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "size", "3"), - resource.TestCheckResourceAttr(accTestDownloadIsoFileName, "verify", "true"), - resource.TestCheckNoResourceAttr(accTestDownloadIsoFileName, "checksum"), - resource.TestCheckNoResourceAttr(accTestDownloadIsoFileName, "checksum_algorithm"), - resource.TestCheckNoResourceAttr(accTestDownloadIsoFileName, "decompression_algorithm"), - ) + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: accProviders, + Steps: tt.steps, + }) + }) + } } diff --git a/fwprovider/tests/resource_file_test.go b/fwprovider/tests/resource_file_test.go index d87b9f1d..a89be393 100644 --- a/fwprovider/tests/resource_file_test.go +++ b/fwprovider/tests/resource_file_test.go @@ -85,12 +85,12 @@ func TestAccResourceFile(t *testing.T) { Config: testAccResourceFileMissingSourceConfig(), ExpectError: regexp.MustCompile("missing argument"), }, - // Do not allow to overwrite the a file + // Do not allow to overwrite the file { Config: testAccResourceFileCreatedConfig(snippetFile2.Name(), "overwrite = false"), ExpectError: regexp.MustCompile("already exists"), }, - // Allow to overwrite the a file by default + // Allow to overwrite the file by default { Config: testAccResourceFileCreatedConfig(snippetFile2.Name()), Check: testAccResourceFileCreatedCheck("snippets", snippetFile2.Name()), diff --git a/fwprovider/tests/resource_vm_test.go b/fwprovider/tests/resource_vm_test.go index 2642ce34..f9f8ef0f 100644 --- a/fwprovider/tests/resource_vm_test.go +++ b/fwprovider/tests/resource_vm_test.go @@ -8,12 +8,9 @@ package tests import ( "context" - "fmt" - "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) func TestAccResourceVM(t *testing.T) { @@ -343,24 +340,3 @@ func TestAccResourceVMDisks(t *testing.T) { }) } } - -func testResourceAttributes(res string, attrs map[string]string) resource.TestCheckFunc { - return func(s *terraform.State) error { - for k, v := range attrs { - if err := resource.TestCheckResourceAttrWith(res, k, func(got string) error { - match, err := regexp.Match(v, []byte(got)) //nolint:mirror - if err != nil { - return fmt.Errorf("error matching '%s': %w", v, err) - } - if !match { - return fmt.Errorf("expected '%s' to match '%s'", got, v) - } - return nil - })(s); err != nil { - return err - } - } - - return nil - } -} diff --git a/fwprovider/tests/test_support.go b/fwprovider/tests/test_support.go index 17d84506..3c75f01b 100644 --- a/fwprovider/tests/test_support.go +++ b/fwprovider/tests/test_support.go @@ -9,6 +9,7 @@ package tests import ( "context" "fmt" + "regexp" "sync" "testing" @@ -17,7 +18,9 @@ import ( "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/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/stretchr/testify/require" "github.com/bpg/terraform-provider-proxmox/fwprovider" @@ -113,3 +116,36 @@ func getNodeStorageClient() *storage.Client { nodesClient := getNodesClient() return &storage.Client{Client: nodesClient, StorageName: accTestStorageName} } + +func testResourceAttributes(res string, attrs map[string]string) resource.TestCheckFunc { + return func(s *terraform.State) error { + for k, v := range attrs { + if err := resource.TestCheckResourceAttrWith(res, k, func(got string) error { + match, err := regexp.Match(v, []byte(got)) //nolint:mirror + if err != nil { + return fmt.Errorf("error matching '%s': %w", v, err) + } + if !match { + return fmt.Errorf("expected '%s' to match '%s'", got, v) + } + return nil + })(s); err != nil { + return err + } + } + + return nil + } +} + +func testNoResourceAttributes(res string, attrs []string) resource.TestCheckFunc { + return func(s *terraform.State) error { + for _, k := range attrs { + if err := resource.TestCheckNoResourceAttr(res, k)(s); err != nil { + return err + } + } + + return nil + } +} diff --git a/templates/guides/cloud-image.md.tmpl b/templates/guides/cloud-image.md.tmpl index a0bc89af..b86d7af5 100644 --- a/templates/guides/cloud-image.md.tmpl +++ b/templates/guides/cloud-image.md.tmpl @@ -1,8 +1,7 @@ --- layout: page -title: Create a VM from a Cloud Image -parent: Guides -subcategory: Virtual Environment +page_title: "Create a VM from a Cloud Image" +subcategory: Guides description: |- This guide explains how to create a VM from a cloud image. --- diff --git a/templates/guides/cloud-init.md.tmpl b/templates/guides/cloud-init.md.tmpl index cd290285..2b582516 100644 --- a/templates/guides/cloud-init.md.tmpl +++ b/templates/guides/cloud-init.md.tmpl @@ -1,8 +1,7 @@ --- layout: page -title: Configure a VM with Cloud-Init -parent: Guides -subcategory: Virtual Environment +page_title: "Configure a VM with Cloud-Init" +subcategory: Guides description: |- This guide explains how to use the Proxmox provider to create and manage virtual machines using cloud-init. --- diff --git a/templates/guides/setup-proxmox-for-tests.md.tmpl b/templates/guides/setup-proxmox-for-tests.md.tmpl index bb64190c..2d2f9f72 100644 --- a/templates/guides/setup-proxmox-for-tests.md.tmpl +++ b/templates/guides/setup-proxmox-for-tests.md.tmpl @@ -1,8 +1,7 @@ --- layout: page -title: Setup a VM with Proxmox -parent: Guides -subcategory: Virtual Environment +page_title: "Setup a VM with Proxmox" +subcategory: Guides description: |- This guide will help you setup a proxmox node in VM using virt-manager for a job. --- @@ -93,4 +92,4 @@ Goal is to have a proxmox node in VM using for a job 10. Now you can run `make example`. -11. If you see error with proxmox_virtual_environment_file: the datastore "local" does not support content type "snippets"; supported content types are: [backup iso vztmpl], you need to enable them, see . +11. If you see error with proxmox_virtual_environment_file: the datastore "local" does not support content type "snippets"; supported content types are: `[backup, iso, vztmpl]`, you need to enable them, see .