Files
terraform-provider-vault-se…/internal/provider/resource_secret_backend_role_test.go
T
unkin-agent 98550e5b68
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Model apps as a set instead of an ordered list
The arrstack engine returns apps alphabetically sorted, so a List
attribute produces 'inconsistent result after apply' and perpetual
re-diffs whenever config order differs. apps is semantically a set.
2026-08-22 23:23:49 +10:00

123 lines
3.5 KiB
Go

package provider
import (
"context"
"encoding/json"
"testing"
"github.com/hashicorp/terraform-plugin-framework/types"
)
func setOf(t *testing.T, vals ...string) types.Set {
t.Helper()
s, diags := types.SetValueFrom(context.Background(), types.StringType, vals)
if diags.HasError() {
t.Fatalf("building set: %v", diags)
}
return s
}
func TestRoleDataOmitsUnsetTTLs(t *testing.T) {
m := secretBackendRoleModel{
Apps: setOf(t, "sonarr", "radarr", "prowlarr"),
TTL: types.Int64Null(),
MaxTTL: types.Int64Null(),
}
data, diags := roleData(context.Background(), m)
if diags.HasError() {
t.Fatalf("roleData: %v", diags)
}
apps, ok := data["apps"].([]string)
if !ok || len(apps) != 3 || apps[0] != "sonarr" {
t.Errorf("apps = %v, want [sonarr radarr prowlarr]", data["apps"])
}
if _, ok := data["ttl"]; ok {
t.Errorf("ttl should be omitted when null")
}
if _, ok := data["max_ttl"]; ok {
t.Errorf("max_ttl should be omitted when null")
}
}
func TestRoleDataIncludesTTLs(t *testing.T) {
m := secretBackendRoleModel{
Apps: setOf(t, "prowlarr"),
TTL: types.Int64Value(60),
MaxTTL: types.Int64Value(86400),
}
data, diags := roleData(context.Background(), m)
if diags.HasError() {
t.Fatalf("roleData: %v", diags)
}
if data["ttl"] != int64(60) {
t.Errorf("ttl = %v, want 60", data["ttl"])
}
if data["max_ttl"] != int64(86400) {
t.Errorf("max_ttl = %v, want 86400", data["max_ttl"])
}
}
func TestApplyRoleDataMapsEngineResponse(t *testing.T) {
// Shape mirrors what the engine's role read returns via the Vault API.
role := map[string]interface{}{
"apps": []interface{}{"sonarr", "radarr", "prowlarr"},
"ttl": json.Number("60"),
"max_ttl": json.Number("86400"),
}
var m secretBackendRoleModel
m.TTL = types.Int64Null()
m.MaxTTL = types.Int64Null()
if diags := applyRoleData(&m, role); diags.HasError() {
t.Fatalf("applyRoleData: %v", diags)
}
if !m.Apps.Equal(setOf(t, "sonarr", "radarr", "prowlarr")) {
t.Errorf("apps = %v, want {sonarr radarr prowlarr}", m.Apps)
}
if m.TTL.ValueInt64() != 60 || m.MaxTTL.ValueInt64() != 86400 {
t.Errorf("ttl/max_ttl = %d/%d, want 60/86400", m.TTL.ValueInt64(), m.MaxTTL.ValueInt64())
}
}
func TestApplyRoleDataOrderInsensitive(t *testing.T) {
// The engine returns apps alphabetically sorted regardless of the order
// they were written in; the read-back must still equal the config value.
configApps := setOf(t, "sonarr", "prowlarr", "radarr")
role := map[string]interface{}{
"apps": []interface{}{"prowlarr", "radarr", "sonarr"},
}
m := secretBackendRoleModel{
Apps: configApps,
TTL: types.Int64Null(),
MaxTTL: types.Int64Null(),
}
if diags := applyRoleData(&m, role); diags.HasError() {
t.Fatalf("applyRoleData: %v", diags)
}
if !m.Apps.Equal(configApps) {
t.Errorf("apps after read-back = %v, not equal to config value %v", m.Apps, configApps)
}
}
func TestApplyRoleDataZeroTTLLeavesNull(t *testing.T) {
// The engine returns 0 for an unset TTL, which must not clobber the null
// model value into a spurious 0.
role := map[string]interface{}{
"apps": []interface{}{"sonarr"},
"ttl": json.Number("0"),
"max_ttl": json.Number("0"),
}
m := secretBackendRoleModel{
TTL: types.Int64Null(),
MaxTTL: types.Int64Null(),
}
if diags := applyRoleData(&m, role); diags.HasError() {
t.Fatalf("applyRoleData: %v", diags)
}
if !m.TTL.IsNull() {
t.Errorf("ttl = %v, want null", m.TTL)
}
if !m.MaxTTL.IsNull() {
t.Errorf("max_ttl = %v, want null", m.MaxTTL)
}
}