Skip to content

Commit

Permalink
test(iam): member assignment acceptance tests (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndopj authored Oct 31, 2023
1 parent c9681c0 commit f8daf3b
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 144 deletions.
5 changes: 0 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ require (
github.com/hashicorp/terraform-registry-address v0.2.2 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
Expand All @@ -52,7 +50,6 @@ require (
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/stretchr/objx v0.5.1 // indirect
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v5 v5.4.0 // indirect
Expand All @@ -65,12 +62,10 @@ require (
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/grpc v1.59.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
nhooyr.io/websocket v1.8.9 // indirect
)
113 changes: 5 additions & 108 deletions go.sum

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions monte_carlo/client/monte_carlo_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,11 @@ type GetTables struct {
}

type User struct {
Id string
Email string
FirstName string
LastName string
IsSso bool
CognitoUserId string
Email string
FirstName string
LastName string
IsSso bool
}

type AuthorizationGroup struct {
Expand All @@ -232,7 +232,7 @@ type AuthorizationGroup struct {
type CreateOrUpdateAuthorizationGroup struct {
CreateOrUpdateAuthorizationGroup struct {
AuthorizationGroup AuthorizationGroup
} `graphql:"createOrUpdateAuthorizationGroup(name: $name, label: $label, description: $description, roles: $roles, domainRestrictionIds: $domainRestrictionIds, ssoGroup: $ssoGroup)"`
} `graphql:"createOrUpdateAuthorizationGroup(name: $name, label: $label, description: $description, roles: $roles, memberUserIds: $memberUserIds, domainRestrictionIds: $domainRestrictionIds, ssoGroup: $ssoGroup)"`
}

type GetAuthorizationGroups struct {
Expand All @@ -247,13 +247,13 @@ type DeleteAuthorizationGroup struct {

type GetUsersInAccount struct {
GetUsersInAccount struct {
Edges []struct{
Edges []struct {
Node User
}
PageInfo struct {
StartCursor string
EndCursor string
HasNextPage bool
}
} `graphql:"getTables(email: $email, first: $first, after: $after)"`
} `graphql:"getUsersInAccount(email: $email, first: $first, after: $after)"`
}
1 change: 1 addition & 0 deletions monte_carlo/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func (p *Provider) Resources(ctx context.Context) []func() resource.Resource {
resources.NewTransactionalWarehouseResource,
resources.NewDomainResource,
resources.NewIamGroupResource,
resources.NewIamMemberResource,
}
}

Expand Down
10 changes: 6 additions & 4 deletions monte_carlo/resources/iam_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ func (r *IamGroupResource) Create(ctx context.Context, req resource.CreateReques
"roles": []string{data.Role.ValueString()},
"domainRestrictionIds": normalize[client.UUID](data.Domains),
"ssoGroup": data.SsoGroup.ValueStringPointer(),
"memberUserIds": (*[]string)(nil),
}

if err := r.client.Mutate(ctx, &createResult, variables); err == nil {
Expand Down Expand Up @@ -165,7 +166,7 @@ func (r *IamGroupResource) Read(ctx context.Context, req resource.ReadRequest, r
data.Label = types.StringValue(found.Label)
data.Description = types.StringValue(found.Description)
data.Role = denormalize(rolesToNames(found.Roles))[0]
data.Domains = denormalize(domainsToUuids(found.DomainRestrictions))
data.Domains = denormalize(domainsToUuids[string](found.DomainRestrictions))
data.SsoGroup = types.StringPointerValue(found.SsoGroup)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
Expand All @@ -186,6 +187,7 @@ func (r *IamGroupResource) Update(ctx context.Context, req resource.UpdateReques
"roles": []string{data.Role.ValueString()},
"domainRestrictionIds": normalize[client.UUID](data.Domains),
"ssoGroup": data.SsoGroup.ValueStringPointer(),
"memberUserIds": (*[]string)(nil),
}

if err := r.client.Mutate(ctx, &updateResult, variables); err == nil {
Expand Down Expand Up @@ -230,10 +232,10 @@ func rolesToNames(roles []struct{ Name string }) []string {
return result
}

func domainsToUuids(domains []struct{ Uuid string }) []string {
result := make([]string, len(domains))
func domainsToUuids[T ~string](domains []struct{ Uuid string }) []T {
result := make([]T, len(domains))
for i, domain := range domains {
result[i] = domain.Uuid
result[i] = T(domain.Uuid)
}
return result
}
3 changes: 1 addition & 2 deletions monte_carlo/resources/iam_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ func TestAccIamGroupResource(t *testing.T) {
ImportStateId: name,
ImportStateVerifyIdentifierAttribute: "name",
},
// Update and Read testing
{
{ // Update and Read testing
Config: iamGroupConfig(name, roleUpdate, &domainsUpdate, &ssoGroupUpdate),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("montecarlo_iam_group.test", "name", name),
Expand Down
44 changes: 27 additions & 17 deletions monte_carlo/resources/iam_member.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/kiwicom/terraform-provider-montecarlo/monte_carlo/common"

"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
Expand All @@ -20,7 +21,7 @@ import (
)

var groupsRegex = regexp.MustCompile(`^groups/.+$`)
var memberRegex = regexp.MustCompile(`^user/.+$`)
var memberRegex = regexp.MustCompile(`^user:.+$`)

// Ensure provider defined types fully satisfy framework interfaces.
var _ resource.Resource = &IamMemberResource{}
Expand Down Expand Up @@ -56,7 +57,7 @@ func (r *IamMemberResource) Schema(ctx context.Context, req resource.SchemaReque
stringplanmodifier.RequiresReplaceIfConfigured(),
},
Validators: []validator.String{
stringvalidator.RegexMatches(groupsRegex, "Expected format: groups/{group_name}"),
stringvalidator.RegexMatches(groupsRegex, "Expected format - groups/{group_name}"),
},
},
"member": schema.StringAttribute{
Expand All @@ -65,7 +66,7 @@ func (r *IamMemberResource) Schema(ctx context.Context, req resource.SchemaReque
stringplanmodifier.RequiresReplaceIfConfigured(),
},
Validators: []validator.String{
stringvalidator.RegexMatches(memberRegex, "Expected format: user/{user_email}"),
stringvalidator.RegexMatches(memberRegex, "Expected format - user:{user_email}"),
},
},
"member_id": schema.StringAttribute{
Expand All @@ -92,7 +93,7 @@ func (r *IamMemberResource) Create(ctx context.Context, req resource.CreateReque
return
}

userEmail := strings.Split(data.Member.ValueString(), "user/")[1]
userEmail := strings.Split(data.Member.ValueString(), "user:")[1]
getUserResult := client.GetUsersInAccount{}
variables := map[string]interface{}{
"email": userEmail,
Expand All @@ -101,7 +102,7 @@ func (r *IamMemberResource) Create(ctx context.Context, req resource.CreateReque
}

if err := r.client.Query(ctx, &getUserResult, variables); err != nil {
to_print := fmt.Sprintf("MC client 'getTables' query result - %s", err.Error())
to_print := fmt.Sprintf("MC client 'getUsersInAccount' query result - %s", err.Error())
resp.Diagnostics.AddError(to_print, "")
return
} else if len(getUserResult.GetUsersInAccount.Edges) == 0 {
Expand Down Expand Up @@ -131,9 +132,9 @@ func (r *IamMemberResource) Create(ctx context.Context, req resource.CreateReque
}

memberUserIds := make([]string, len(found.Users)+1)
memberUserIds[len(found.Users)] = getUserResult.GetUsersInAccount.Edges[0].Node.Id
memberUserIds[len(found.Users)] = getUserResult.GetUsersInAccount.Edges[0].Node.CognitoUserId
for i, user := range found.Users {
memberUserIds[i] = user.Id
memberUserIds[i] = user.CognitoUserId
}

updateResult := client.CreateOrUpdateAuthorizationGroup{}
Expand All @@ -142,7 +143,7 @@ func (r *IamMemberResource) Create(ctx context.Context, req resource.CreateReque
"label": found.Label,
"description": found.Description,
"roles": rolesToNames(found.Roles),
"domainRestrictionIds": domainsToUuids(found.DomainRestrictions),
"domainRestrictionIds": domainsToUuids[client.UUID](found.DomainRestrictions),
"ssoGroup": found.SsoGroup,
"memberUserIds": memberUserIds,
}
Expand All @@ -151,7 +152,7 @@ func (r *IamMemberResource) Create(ctx context.Context, req resource.CreateReque
to_print := fmt.Sprintf("MC client 'createOrUpdateAuthorizationGroup' mutation result - %s", err.Error())
resp.Diagnostics.AddError(to_print, "")
} else {
data.MemberId = types.StringValue(getUserResult.GetUsersInAccount.Edges[0].Node.Id)
data.MemberId = types.StringValue(getUserResult.GetUsersInAccount.Edges[0].Node.CognitoUserId)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
}
Expand All @@ -163,7 +164,7 @@ func (r *IamMemberResource) Read(ctx context.Context, req resource.ReadRequest,
return
}

userEmail := strings.Split(data.Member.ValueString(), "user/")[1]
userEmail := strings.Split(data.Member.ValueString(), "user:")[1]
getUserResult := client.GetUsersInAccount{}
variables := map[string]interface{}{
"email": userEmail,
Expand All @@ -172,7 +173,7 @@ func (r *IamMemberResource) Read(ctx context.Context, req resource.ReadRequest,
}

if err := r.client.Query(ctx, &getUserResult, variables); err != nil {
to_print := fmt.Sprintf("MC client 'getTables' query result - %s", err.Error())
to_print := fmt.Sprintf("MC client 'getUsersInAccount' query result - %s", err.Error())
resp.Diagnostics.AddError(to_print, "")
return
} else if len(getUserResult.GetUsersInAccount.Edges) == 0 {
Expand Down Expand Up @@ -200,13 +201,14 @@ func (r *IamMemberResource) Read(ctx context.Context, req resource.ReadRequest,

if found == nil || found.SsoGroup != nil {
to_print := fmt.Sprintf("Group %s not found or is SSO managed", data.Group.ValueString())
resp.Diagnostics.AddError(to_print, "")
resp.Diagnostics.AddWarning(to_print, "")
resp.State.RemoveResource(ctx)
} else if !slices.Contains(found.Users, getUserResult.GetUsersInAccount.Edges[0].Node) {
to_print := fmt.Sprintf("User %s not found in group %s", userEmail, data.Group.ValueString())
resp.Diagnostics.AddWarning(to_print, "")
resp.State.RemoveResource(ctx)
} else {
data.MemberId = types.StringValue(getUserResult.GetUsersInAccount.Edges[0].Node.Id)
data.MemberId = types.StringValue(getUserResult.GetUsersInAccount.Edges[0].Node.CognitoUserId)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
}
Expand All @@ -227,7 +229,7 @@ func (r *IamMemberResource) Delete(ctx context.Context, req resource.DeleteReque
variables := map[string]interface{}{}
if err := r.client.Query(ctx, &getGroupResult, variables); err != nil {
to_print := fmt.Sprintf("MC client 'GetAuthorizationGroups' query result - %s", err.Error())
resp.Diagnostics.AddWarning(to_print, "")
resp.Diagnostics.AddError(to_print, "")
return
}

Expand All @@ -244,7 +246,7 @@ func (r *IamMemberResource) Delete(ctx context.Context, req resource.DeleteReque

memberUserIds := make([]string, len(found.Users))
for i, user := range found.Users {
memberUserIds[i] = user.Id
memberUserIds[i] = user.CognitoUserId
}

updateResult := client.CreateOrUpdateAuthorizationGroup{}
Expand All @@ -254,7 +256,7 @@ func (r *IamMemberResource) Delete(ctx context.Context, req resource.DeleteReque
"label": found.Label,
"description": found.Description,
"roles": rolesToNames(found.Roles),
"domainRestrictionIds": domainsToUuids(found.DomainRestrictions),
"domainRestrictionIds": domainsToUuids[client.UUID](found.DomainRestrictions),
"ssoGroup": found.SsoGroup,
"memberUserIds": memberUserIds,
}
Expand All @@ -266,5 +268,13 @@ func (r *IamMemberResource) Delete(ctx context.Context, req resource.DeleteReque
}

func (r *IamMemberResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
// TODO
idsImported := strings.Split(req.ID, ",")
if len(idsImported) == 2 && idsImported[0] != "" && idsImported[1] != "" {
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("group"), idsImported[0])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("member"), idsImported[1])...)
} else {
resp.Diagnostics.AddError("Unexpected Import Identifier", fmt.Sprintf(
"Expected import identifier with format: groups/<group_name>,user:<user_email>. Got: %q", req.ID),
)
}
}
Loading

0 comments on commit f8daf3b

Please sign in to comment.