0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-08-22 11:28:33 +00:00

fix(acme): fix ACME account management & add acceptance tests (#2072)

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
Pavel Boldyrev 2025-07-31 22:06:07 -04:00 committed by GitHub
parent 6b73d822a5
commit 3f5b795a84
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 601 additions and 0 deletions

View File

@ -0,0 +1,63 @@
//go:build acceptance || all
/*
* 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 acme_test
import (
"fmt"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
)
func TestAccDatasourceACMEAccount(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
accountName := fmt.Sprintf("test-ds-account-%s", gofakeit.Word())
te.AddTemplateVars(map[string]interface{}{
"AccountName": accountName,
})
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_account" "test_account" {
name = "{{.AccountName}}"
contact = "le.ge9ro@passmail.net"
directory = "https://acme-staging-v02.api.letsencrypt.org/directory"
tos = "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
}
data "proxmox_virtual_environment_acme_account" "test" {
depends_on = [proxmox_virtual_environment_acme_account.test_account]
name = "{{.AccountName}}"
}
`, test.WithRootUser()),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("data.proxmox_virtual_environment_acme_account.test", map[string]string{
"name": accountName,
}),
test.ResourceAttributesSet("data.proxmox_virtual_environment_acme_account.test", []string{
"account.created_at",
"account.status",
"directory",
"location",
"tos",
}),
resource.TestCheckResourceAttrSet("data.proxmox_virtual_environment_acme_account.test", "account.contact.#"),
),
},
},
})
}

View File

@ -0,0 +1,64 @@
//go:build acceptance || all
/*
* 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 acme_test
import (
"fmt"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
)
func TestAccDatasourceACMEAccounts(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
accountName1 := fmt.Sprintf("test-ds-accounts1-%s", gofakeit.Word())
accountName2 := fmt.Sprintf("test-ds-accounts2-%s", gofakeit.Word())
te.AddTemplateVars(map[string]interface{}{
"AccountName1": accountName1,
"AccountName2": accountName2,
})
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_account" "test_account1" {
name = "{{.AccountName1}}"
contact = "le.ge9ro@passmail.net"
directory = "https://acme-staging-v02.api.letsencrypt.org/directory"
tos = "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
}
resource "proxmox_virtual_environment_acme_account" "test_account2" {
name = "{{.AccountName2}}"
contact = "le.ge9ro@passmail.net"
directory = "https://acme-staging-v02.api.letsencrypt.org/directory"
tos = "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
}
data "proxmox_virtual_environment_acme_accounts" "test" {
depends_on = [
proxmox_virtual_environment_acme_account.test_account1,
proxmox_virtual_environment_acme_account.test_account2
]
}
`, test.WithRootUser()),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.proxmox_virtual_environment_acme_accounts.test", "accounts.#"),
),
},
},
})
}

View File

@ -0,0 +1,63 @@
//go:build acceptance || all
/*
* 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 acme_test
import (
"fmt"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
)
func TestAccDatasourceACMEPlugin(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
pluginName := fmt.Sprintf("test-ds-plugin-%s", gofakeit.Word())
te.AddTemplateVars(map[string]interface{}{
"PluginName": pluginName,
})
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin" {
plugin = "{{.PluginName}}"
api = "cf"
data = {
"CF_API_EMAIL" = "le.ge9ro@passmail.net"
"CF_API_KEY" = "test-api-key"
}
}
data "proxmox_virtual_environment_acme_plugin" "test" {
depends_on = [proxmox_virtual_environment_acme_dns_plugin.test_plugin]
plugin = "{{.PluginName}}"
}
`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("data.proxmox_virtual_environment_acme_plugin.test", map[string]string{
"plugin": pluginName,
}),
test.ResourceAttributesSet("data.proxmox_virtual_environment_acme_plugin.test", []string{
"api",
"digest",
"validation_delay",
}),
resource.TestCheckResourceAttrSet("data.proxmox_virtual_environment_acme_plugin.test", "data.%"),
),
},
},
})
}

View File

@ -0,0 +1,96 @@
//go:build acceptance || all
/*
* 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 acme_test
import (
"fmt"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
)
func TestAccDatasourceACMEPlugins(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
pluginName1 := fmt.Sprintf("test-ds-plugins1-%s", gofakeit.Word())
pluginName2 := fmt.Sprintf("test-ds-plugins2-%s", gofakeit.Word())
te.AddTemplateVars(map[string]interface{}{
"PluginName1": pluginName1,
"PluginName2": pluginName2,
})
// First create some plugins to test against
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin1" {
plugin = "{{.PluginName1}}"
api = "cf"
data = {
"CF_API_EMAIL" = "test1@example.com"
"CF_API_KEY" = "test-api-key-1"
}
}
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin2" {
plugin = "{{.PluginName2}}"
api = "cf"
data = {
"CF_API_EMAIL" = "test2@example.com"
"CF_API_KEY" = "test-api-key-2"
}
}
`),
},
},
})
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin1" {
plugin = "{{.PluginName1}}"
api = "cf"
data = {
"CF_API_EMAIL" = "le.ge9ro@passmail.net"
"CF_API_KEY" = "test-api-key-1"
}
}
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin2" {
plugin = "{{.PluginName2}}"
api = "cf"
data = {
"CF_API_EMAIL" = "le.ge9ro@passmail.net"
"CF_API_KEY" = "test-api-key-2"
}
}
data "proxmox_virtual_environment_acme_plugins" "test" {
depends_on = [
proxmox_virtual_environment_acme_dns_plugin.test_plugin1,
proxmox_virtual_environment_acme_dns_plugin.test_plugin2
]
}
`),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.proxmox_virtual_environment_acme_plugins.test", "plugins.#"),
),
},
},
})
}

View File

@ -4,6 +4,24 @@
* file, You can obtain one at https://mozilla.org/MPL/2.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/.
*/
/*
* 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/.
*/
/*
* 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 acme
import (
@ -305,9 +323,15 @@ func (r *acmeAccountResource) read(ctx context.Context, data *acmeAccountModel)
return false, diags
}
// Preserve the original contact value if the API doesn't return it
originalContact := data.Contact.ValueString()
var contact string
if len(acc.Account.Contact) > 0 {
contact = strings.Replace(acc.Account.Contact[0], "mailto:", "", 1)
} else if originalContact != "" {
// If API doesn't return contact but we had one, preserve it
contact = originalContact
}
data.Directory = types.StringValue(acc.Directory)

View File

@ -0,0 +1,131 @@
//go:build acceptance || all
/*
* 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 acme_test
import (
"fmt"
"regexp"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
)
func TestAccResourceACMEAccount(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
accountName := fmt.Sprintf("test-account-%s", gofakeit.Word())
te.AddTemplateVars(map[string]interface{}{
"AccountName": accountName,
})
tests := []struct {
name string
step []resource.TestStep
}{
{"basic account creation", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_account" "test_account" {
name = "{{.AccountName}}"
contact = "le.ge9ro@passmail.net"
directory = "https://acme-staging-v02.api.letsencrypt.org/directory"
tos = "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
}`, test.WithRootUser()),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_account.test_account", map[string]string{
"name": accountName,
"directory": "https://acme-staging-v02.api.letsencrypt.org/directory",
"tos": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf",
}),
test.ResourceAttributesSet("proxmox_virtual_environment_acme_account.test_account", []string{
"created_at",
"location",
}),
),
},
}},
{"account with EAB", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_account" "test_account_eab" {
name = "{{.AccountName}}-eab"
contact = "le.ge9ro@passmail.net"
directory = "https://acme-staging-v02.api.letsencrypt.org/directory"
tos = "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
eab_hmac_key = "test-hmac-key"
eab_kid = "test-kid"
}`, test.WithRootUser()),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_account.test_account_eab", map[string]string{
"name": fmt.Sprintf("%s-eab", accountName),
"directory": "https://acme-staging-v02.api.letsencrypt.org/directory",
"tos": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf",
"eab_hmac_key": "test-hmac-key",
"eab_kid": "test-kid",
}),
),
},
}},
{"update account", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_account" "test_account_update" {
name = "{{.AccountName}}-update"
contact = "le.ge9ro@passmail.net"
directory = "https://acme-staging-v02.api.letsencrypt.org/directory"
tos = "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
}`, test.WithRootUser()),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_account.test_account_update", map[string]string{
"name": fmt.Sprintf("%s-update", accountName),
}),
),
},
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_account" "test_account_update" {
name = "{{.AccountName}}-update"
contact = "le.ge9ro@passmail.net"
directory = "https://acme-staging-v02.api.letsencrypt.org/directory"
tos = "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
}`, test.WithRootUser()),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_account.test_account_update", map[string]string{
"name": fmt.Sprintf("%s-update", accountName),
}),
),
},
}},
{"invalid directory URL", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_account" "test_account_invalid" {
name = "{{.AccountName}}-invalid"
contact = "le.ge9ro@passmail.net"
directory = "invalid-url"
tos = "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf"
}`, test.WithRootUser()),
ExpectError: regexp.MustCompile(`must be a valid URL`),
},
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.step,
})
})
}
}

View File

@ -0,0 +1,160 @@
//go:build acceptance || all
/*
* 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 acme_test
import (
"fmt"
"regexp"
"testing"
"github.com/brianvoe/gofakeit/v7"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
)
func TestAccResourceACMEDNSPlugin(t *testing.T) {
t.Parallel()
te := test.InitEnvironment(t)
pluginName := fmt.Sprintf("test-plugin-%s", gofakeit.Word())
te.AddTemplateVars(map[string]interface{}{
"PluginName": pluginName,
})
tests := []struct {
name string
step []resource.TestStep
}{
{"basic plugin creation", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin" {
plugin = "{{.PluginName}}"
api = "cf"
data = {
"CF_API_EMAIL" = "test@example.com"
"CF_API_KEY" = "test-api-key"
}
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_dns_plugin.test_plugin", map[string]string{
"plugin": pluginName,
"api": "cf",
}),
test.ResourceAttributesSet("proxmox_virtual_environment_acme_dns_plugin.test_plugin", []string{
"digest",
}),
),
},
}},
{"plugin with validation delay", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin_delay" {
plugin = "{{.PluginName}}-delay"
api = "cf"
data = {
"CF_API_EMAIL" = "test@example.com"
"CF_API_KEY" = "test-api-key"
}
validation_delay = 60
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_dns_plugin.test_plugin_delay", map[string]string{
"plugin": fmt.Sprintf("%s-delay", pluginName),
"api": "cf",
"validation_delay": "60",
}),
),
},
}},
{"plugin with disable flag", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin_disabled" {
plugin = "{{.PluginName}}-disabled"
api = "cf"
data = {
"CF_API_EMAIL" = "test@example.com"
"CF_API_KEY" = "test-api-key"
}
disable = true
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_dns_plugin.test_plugin_disabled", map[string]string{
"plugin": fmt.Sprintf("%s-disabled", pluginName),
"api": "cf",
"disable": "true",
}),
),
},
}},
{"update plugin", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin_update" {
plugin = "{{.PluginName}}-update"
api = "cf"
data = {
"CF_API_EMAIL" = "test@example.com"
"CF_API_KEY" = "test-api-key"
}
validation_delay = 30
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_dns_plugin.test_plugin_update", map[string]string{
"validation_delay": "30",
}),
),
},
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin_update" {
plugin = "{{.PluginName}}-update"
api = "cf"
data = {
"CF_API_EMAIL" = "test@example.com"
"CF_API_KEY" = "test-api-key"
}
validation_delay = 120
}`),
Check: resource.ComposeTestCheckFunc(
test.ResourceAttributes("proxmox_virtual_environment_acme_dns_plugin.test_plugin_update", map[string]string{
"validation_delay": "120",
}),
),
},
}},
{"invalid validation delay", []resource.TestStep{
{
Config: te.RenderConfig(`
resource "proxmox_virtual_environment_acme_dns_plugin" "test_plugin_invalid" {
plugin = "{{.PluginName}}-invalid"
api = "cf"
data = {
"CF_API_EMAIL" = "test@example.com"
"CF_API_KEY" = "test-api-key"
}
validation_delay = 200000
}`),
ExpectError: regexp.MustCompile(`Attribute validation_delay value must be between 0 and 172800`),
},
}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: te.AccProviders,
Steps: tt.step,
})
})
}
}