0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-06-29 18:21:10 +00:00

fix(user): expiration_date attribute handling (#1066)

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
Pavel Boldyrev 2024-02-26 22:06:58 -05:00 committed by GitHub
parent 953a23d2a7
commit 3c5276093a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 127 additions and 63 deletions

View File

@ -23,6 +23,9 @@ issues:
- path: _types\.go
linters:
- lll
- path: fwprovider/tests/.*\.go
linters:
- paralleltest
linters-settings:
exhaustive:
default-signifies-exhaustive: true

View File

@ -5,14 +5,15 @@ resource "proxmox_virtual_environment_user" "example" {
role_id = "PVEVMAdmin"
}
comment = "Managed by Terraform"
password = "Test1234!"
user_id = "terraform-provider-proxmox-example@pve"
comment = "Managed by Terraform"
password = "Test1234!"
user_id = "terraform-provider-proxmox-example@pve"
expiration_date = "2035-12-31T23:59:59Z"
}
resource "proxmox_virtual_environment_user" "example2" {
comment = "Managed by Terraform"
user_id = "terraform-provider-proxmox-example2@pve"
comment = "Managed by Terraform"
user_id = "terraform-provider-proxmox-example2@pve"
}
output "resource_proxmox_virtual_environment_user_example_acl" {

View File

@ -21,7 +21,6 @@ const (
accTestContainerCloneName = "proxmox_virtual_environment_container.test_container_clone"
)
//nolint:paralleltest
func TestAccResourceContainer(t *testing.T) {
accProviders := testAccMuxProviders(context.Background(), t)

View File

@ -23,7 +23,6 @@ const (
fakeFileQCOW2 = "https://cdn.githubraw.com/rafsaf/036eece601975a3ad632a77fc2809046/raw/10500012fca9b4425b50de67a7258a12cba0c076/fake_file.qcow2"
)
//nolint:paralleltest
func TestAccResourceDownloadFile(t *testing.T) {
tests := []struct {
name string

View File

@ -20,7 +20,6 @@ const (
accTestLinuxBridgeName = "proxmox_virtual_environment_network_linux_bridge.test"
)
//nolint:paralleltest
func TestAccResourceLinuxBridge(t *testing.T) {
accProviders := testAccMuxProviders(context.Background(), t)

View File

@ -20,7 +20,6 @@ const (
accTestLinuxVLANName = "proxmox_virtual_environment_network_linux_vlan.test"
)
//nolint:paralleltest
func TestAccResourceLinuxVLAN(t *testing.T) {
accProviders := testAccMuxProviders(context.Background(), t)

View File

@ -0,0 +1,76 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package tests
import (
"context"
"testing"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)
func TestAccResourceUser(t *testing.T) {
tests := []struct {
name string
steps []resource.TestStep
}{
{"create and update user", []resource.TestStep{{
Config: `
resource "proxmox_virtual_environment_user" "user1" {
comment = "Managed by Terraform"
email = "user1@pve"
enabled = true
expiration_date = "2034-01-01T22:00:00Z"
first_name = "First"
last_name = "Last"
//password = "password"
user_id = "user1@pve"
}
`,
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_user.user1", map[string]string{
"comment": "Managed by Terraform",
"email": "user1@pve",
"enabled": "true",
"expiration_date": "2034-01-01T22:00:00Z",
"first_name": "First",
"last_name": "Last",
"user_id": "user1@pve",
}),
),
}, {
Config: `
resource "proxmox_virtual_environment_user" "user1" {
enabled = false
expiration_date = "2035-01-01T22:00:00Z"
user_id = "user1@pve"
first_name = "First One"
}
`,
Check: resource.ComposeTestCheckFunc(
testResourceAttributes("proxmox_virtual_environment_user.user1", map[string]string{
"enabled": "false",
"expiration_date": "2035-01-01T22:00:00Z",
"first_name": "First One",
"user_id": "user1@pve",
}),
),
}}},
}
accProviders := testAccMuxProviders(context.Background(), t)
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: accProviders,
Steps: tt.steps,
})
})
}
}

View File

@ -77,7 +77,6 @@ func TestAccResourceVM(t *testing.T) {
}
}
//nolint:paralleltest
func TestAccResourceVMNetwork(t *testing.T) {
tests := []struct {
name string

View File

@ -12,10 +12,8 @@ import (
"net/http"
"net/url"
"sort"
"time"
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
)
func (c *Client) usersPath() string {
@ -74,11 +72,6 @@ func (c *Client) GetUser(ctx context.Context, id string) (*UserGetResponseData,
return nil, api.ErrNoDataObjectInResponse
}
if resBody.Data.ExpirationDate != nil {
expirationDate := types.CustomTimestamp(time.Time(*resBody.Data.ExpirationDate).UTC())
resBody.Data.ExpirationDate = &expirationDate
}
if resBody.Data.Groups != nil {
sort.Strings(*resBody.Data.Groups)
}
@ -104,11 +97,6 @@ func (c *Client) ListUsers(ctx context.Context) ([]*UserListResponseData, error)
})
for i := range resBody.Data {
if resBody.Data[i].ExpirationDate != nil {
expirationDate := types.CustomTimestamp(time.Time(*resBody.Data[i].ExpirationDate).UTC())
resBody.Data[i].ExpirationDate = &expirationDate
}
if resBody.Data[i].Groups != nil {
sort.Strings(*resBody.Data[i].Groups)
}

View File

@ -18,16 +18,16 @@ type UserChangePasswordRequestBody struct {
// UserCreateRequestBody contains the data for a user create request.
type UserCreateRequestBody struct {
Comment *string `json:"comment,omitempty" url:"comment,omitempty"`
Email *string `json:"email,omitempty" url:"email,omitempty"`
Enabled *types.CustomBool `json:"enable,omitempty" url:"enable,omitempty,int"`
ExpirationDate *types.CustomTimestamp `json:"expire,omitempty" url:"expire,omitempty,unix"`
FirstName *string `json:"firstname,omitempty" url:"firstname,omitempty"`
Groups []string `json:"groups,omitempty" url:"groups,omitempty,comma"`
ID string `json:"userid" url:"userid"`
Keys *string `json:"keys,omitempty" url:"keys,omitempty"`
LastName *string `json:"lastname,omitempty" url:"lastname,omitempty"`
Password string `json:"password" url:"password,omitempty"`
Comment *string `json:"comment,omitempty" url:"comment,omitempty"`
Email *string `json:"email,omitempty" url:"email,omitempty"`
Enabled *types.CustomBool `json:"enable,omitempty" url:"enable,omitempty,int"`
ExpirationDate *int64 `json:"expire,omitempty" url:"expire,omitempty"`
FirstName *string `json:"firstname,omitempty" url:"firstname,omitempty"`
Groups []string `json:"groups,omitempty" url:"groups,omitempty,comma"`
ID string `json:"userid" url:"userid"`
Keys *string `json:"keys,omitempty" url:"keys,omitempty"`
LastName *string `json:"lastname,omitempty" url:"lastname,omitempty"`
Password string `json:"password" url:"password,omitempty"`
}
// UserGetResponseBody contains the body from a user get response.
@ -37,14 +37,14 @@ type UserGetResponseBody struct {
// UserGetResponseData contains the data from an user get response.
type UserGetResponseData struct {
Comment *string `json:"comment,omitempty"`
Email *string `json:"email,omitempty"`
Enabled *types.CustomBool `json:"enable,omitempty"`
ExpirationDate *types.CustomTimestamp `json:"expire,omitempty"`
FirstName *string `json:"firstname,omitempty"`
Groups *[]string `json:"groups,omitempty"`
Keys *string `json:"keys,omitempty"`
LastName *string `json:"lastname,omitempty"`
Comment *string `json:"comment,omitempty"`
Email *string `json:"email,omitempty"`
Enabled *types.CustomBool `json:"enable,omitempty"`
ExpirationDate *int64 `json:"expire,omitempty"`
FirstName *string `json:"firstname,omitempty"`
Groups *[]string `json:"groups,omitempty"`
Keys *string `json:"keys,omitempty"`
LastName *string `json:"lastname,omitempty"`
}
// UserListResponseBody contains the body from a user list response.
@ -54,26 +54,26 @@ type UserListResponseBody struct {
// UserListResponseData contains the data from an user list response.
type UserListResponseData struct {
Comment *string `json:"comment,omitempty"`
Email *string `json:"email,omitempty"`
Enabled *types.CustomBool `json:"enable,omitempty"`
ExpirationDate *types.CustomTimestamp `json:"expire,omitempty"`
FirstName *string `json:"firstname,omitempty"`
Groups *[]string `json:"groups,omitempty"`
ID string `json:"userid"`
Keys *string `json:"keys,omitempty"`
LastName *string `json:"lastname,omitempty"`
Comment *string `json:"comment,omitempty"`
Email *string `json:"email,omitempty"`
Enabled *types.CustomBool `json:"enable,omitempty"`
ExpirationDate *int64 `json:"expire,omitempty"`
FirstName *string `json:"firstname,omitempty"`
Groups *[]string `json:"groups,omitempty"`
ID string `json:"userid"`
Keys *string `json:"keys,omitempty"`
LastName *string `json:"lastname,omitempty"`
}
// UserUpdateRequestBody contains the data for an user update request.
type UserUpdateRequestBody struct {
Append *types.CustomBool `json:"append,omitempty" url:"append,omitempty"`
Comment *string `json:"comment,omitempty" url:"comment,omitempty"`
Email *string `json:"email,omitempty" url:"email,omitempty"`
Enabled *types.CustomBool `json:"enable,omitempty" url:"enable,omitempty,int"`
ExpirationDate *types.CustomTimestamp `json:"expire,omitempty" url:"expire,omitempty,unix"`
FirstName *string `json:"firstname,omitempty" url:"firstname,omitempty"`
Groups []string `json:"groups,omitempty" url:"groups,omitempty,comma"`
Keys *string `json:"keys,omitempty" url:"keys,omitempty"`
LastName *string `json:"lastname,omitempty" url:"lastname,omitempty"`
Append *types.CustomBool `json:"append,omitempty" url:"append,omitempty"`
Comment *string `json:"comment,omitempty" url:"comment,omitempty"`
Email *string `json:"email,omitempty" url:"email,omitempty"`
Enabled *types.CustomBool `json:"enable,omitempty" url:"enable,omitempty,int"`
ExpirationDate *int64 `json:"expire,omitempty" url:"expire,omitempty,int"`
FirstName *string `json:"firstname,omitempty" url:"firstname,omitempty"`
Groups []string `json:"groups,omitempty" url:"groups,omitempty,comma"`
Keys *string `json:"keys,omitempty" url:"keys,omitempty"`
LastName *string `json:"lastname,omitempty" url:"lastname,omitempty"`
}

View File

@ -178,7 +178,7 @@ func userRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
diags = append(diags, diag.FromErr(err)...)
if v.ExpirationDate != nil {
t := time.Time(*v.ExpirationDate)
t := time.Unix(*v.ExpirationDate, 0)
if t.Unix() > 0 {
err = d.Set(
mkDataSourceVirtualEnvironmentUserExpirationDate,

View File

@ -138,7 +138,7 @@ func usersRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.
}
if v.ExpirationDate != nil {
t := time.Time(*v.ExpirationDate)
t := time.Unix(*v.ExpirationDate, 0)
if t.Unix() > 0 {
expirationDates[i] = t.UTC().Format(time.RFC3339)

View File

@ -132,6 +132,7 @@ func User() *schema.Resource {
Type: schema.TypeString,
Description: "The user's password",
Optional: true,
Sensitive: true,
},
mkResourceVirtualEnvironmentUserUserID: {
Type: schema.TypeString,
@ -168,7 +169,7 @@ func userCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag
return diag.FromErr(err)
}
expirationDateCustom := types.CustomTimestamp(expirationDate)
expirationDateCustom := expirationDate.Unix()
firstName := d.Get(mkResourceVirtualEnvironmentUserFirstName).(string)
groups := d.Get(mkResourceVirtualEnvironmentUserGroups).(*schema.Set).List()
groupsCustom := make([]string, len(groups))
@ -303,7 +304,7 @@ func userRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
if user.ExpirationDate != nil {
err = d.Set(
mkResourceVirtualEnvironmentUserExpirationDate,
time.Time(*user.ExpirationDate).Format(time.RFC3339),
time.Unix(*user.ExpirationDate, 0).UTC().Format(time.RFC3339),
)
} else {
err = d.Set(mkResourceVirtualEnvironmentUserExpirationDate, time.Unix(0, 0).UTC().Format(time.RFC3339))
@ -363,7 +364,7 @@ func userUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag
return diag.FromErr(err)
}
expirationDateCustom := types.CustomTimestamp(expirationDate)
expirationDateCustom := expirationDate.Unix()
firstName := d.Get(mkResourceVirtualEnvironmentUserFirstName).(string)
groups := d.Get(mkResourceVirtualEnvironmentUserGroups).(*schema.Set).List()
groupsCustom := make([]string, len(groups))