Preserve order of project members even if API re-orders them (#484)

* Preserve order of project members even if API re-orders them

* Adjust role field description

* Fix backwards compatibility of deprecated owner_email field

* Fix typo
This commit is contained in:
João Palet 2024-07-30 13:32:49 +01:00 committed by GitHub
parent 63b07c4422
commit 8dc894cacc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 174 additions and 38 deletions

View file

@ -12,6 +12,7 @@ import (
"github.com/gorilla/mux"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/authorization"
@ -165,6 +166,7 @@ func TestMapProjectFields(t *testing.T) {
func TestMapMembersFields(t *testing.T) {
tests := []struct {
description string
configMembers basetypes.ListValue
membersResp *[]authorization.Member
expected Model
expectedLabels *map[string]string
@ -172,6 +174,7 @@ func TestMapMembersFields(t *testing.T) {
}{
{
"default_ok",
types.ListNull(types.ObjectType{AttrTypes: memberTypes}),
&[]authorization.Member{
{
Subject: utils.Ptr("owner_email"),
@ -209,8 +212,64 @@ func TestMapMembersFields(t *testing.T) {
nil,
true,
},
{
"default_ok (preserve model order)",
types.ListValueMust(types.ObjectType{AttrTypes: memberTypes}, []attr.Value{
types.ObjectValueMust(
memberTypes,
map[string]attr.Value{
"subject": types.StringValue("reader_email"),
"role": types.StringValue("reader"),
},
),
types.ObjectValueMust(
memberTypes,
map[string]attr.Value{
"subject": types.StringValue("owner_email"),
"role": types.StringValue("owner"),
},
),
}),
&[]authorization.Member{
{
Subject: utils.Ptr("owner_email"),
Role: utils.Ptr("owner"),
},
{
Subject: utils.Ptr("reader_email"),
Role: utils.Ptr("reader"),
},
},
Model{
Id: types.StringNull(),
ProjectId: types.StringNull(),
ContainerId: types.StringNull(),
ContainerParentId: types.StringNull(),
Name: types.StringNull(),
Labels: types.MapNull(types.StringType),
Members: types.ListValueMust(types.ObjectType{AttrTypes: memberTypes}, []attr.Value{
types.ObjectValueMust(
memberTypes,
map[string]attr.Value{
"subject": types.StringValue("reader_email"),
"role": types.StringValue("reader"),
},
),
types.ObjectValueMust(
memberTypes,
map[string]attr.Value{
"subject": types.StringValue("owner_email"),
"role": types.StringValue("owner"),
},
),
}),
},
nil,
true,
},
{
"empty members",
types.ListNull(types.ObjectType{AttrTypes: memberTypes}),
&[]authorization.Member{},
Model{
Id: types.StringNull(),
@ -226,6 +285,7 @@ func TestMapMembersFields(t *testing.T) {
},
{
"nil members",
types.ListNull(types.ObjectType{AttrTypes: memberTypes}),
nil,
Model{
Id: types.StringNull(),
@ -250,7 +310,10 @@ func TestMapMembersFields(t *testing.T) {
Name: types.StringNull(),
Labels: types.MapNull(types.StringType),
}
err := mapMembersFields(tt.membersResp, state)
if !tt.configMembers.IsNull() {
state.Members = tt.configMembers
}
err := mapMembersFields(context.Background(), tt.membersResp, state)
if !tt.isValid && err == nil {
t.Fatalf("Should have failed")
}
@ -275,18 +338,6 @@ func TestToCreatePayload(t *testing.T) {
expected *resourcemanager.CreateProjectPayload
isValid bool
}{
{
"default_ok",
&Model{},
nil,
&resourcemanager.CreateProjectPayload{
ContainerParentId: nil,
Labels: nil,
Members: nil,
Name: nil,
},
true,
},
{
"mapping_with_conversions_single_member",
&Model{
@ -404,6 +455,43 @@ func TestToCreatePayload(t *testing.T) {
},
true,
},
{
"deprecated owner_email field still works",
&Model{
ContainerParentId: types.StringValue("pid"),
Name: types.StringValue("name"),
OwnerEmail: types.StringValue("some_email_deprecated"),
},
&map[string]string{
"label1": "1",
"label2": "2",
},
&resourcemanager.CreateProjectPayload{
ContainerParentId: utils.Ptr("pid"),
Labels: &map[string]string{
"label1": "1",
"label2": "2",
},
Members: &[]resourcemanager.Member{
{
Subject: utils.Ptr("some_email_deprecated"),
Role: utils.Ptr("owner"),
},
},
Name: utils.Ptr("name"),
},
true,
},
{
"no members or owner_email fails",
&Model{
ContainerParentId: types.StringValue("pid"),
Name: types.StringValue("name"),
},
&map[string]string{},
nil,
false,
},
{
"nil_model",
nil,