Skip to content

Commit

Permalink
refactor(project_user): replaced client-v2 with avngen
Browse files Browse the repository at this point in the history
  • Loading branch information
vmyroslav committed Jan 7, 2025
1 parent 0759bfb commit 481e1a2
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 115 deletions.
201 changes: 111 additions & 90 deletions internal/sdkprovider/service/project/project_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"errors"
"strings"

"github.com/aiven/aiven-go-client/v2"
avngen "github.com/aiven/go-client-codegen"
"github.com/aiven/go-client-codegen/handler/account"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/aiven/go-client-codegen/handler/project"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/aiven/terraform-provider-aiven/internal/common"
Expand Down Expand Up @@ -44,10 +44,10 @@ func ResourceProjectUser() *schema.Resource {
[migrate existing aiven_project_user resources](https://registry.terraform.io/providers/aiven/aiven/latest/docs/guides/update-deprecated-resources)
to the new resource.
`,
CreateContext: resourceProjectUserCreate,
ReadContext: resourceProjectUserRead,
UpdateContext: resourceProjectUserUpdate,
DeleteContext: resourceProjectUserDelete,
CreateContext: common.WithGenClient(resourceProjectUserCreate),
ReadContext: common.WithGenClient(resourceProjectUserRead),
UpdateContext: common.WithGenClient(resourceProjectUserUpdate),
DeleteContext: common.WithGenClient(resourceProjectUserDelete),
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Expand All @@ -58,139 +58,160 @@ to the new resource.
}
}

// isProjectUserAlreadyInvited return true if user already been invited to the project
func isProjectUserAlreadyInvited(err error) bool {
var e aiven.Error
if errors.As(err, &e) {
if strings.Contains(e.Message, "already been invited to this project") && e.Status == 409 {
return true
}
}
return false
}

func resourceProjectUserCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*aiven.Client)
projectName := d.Get("project").(string)
email := d.Get("email").(string)
err := client.ProjectUsers.Invite(
ctx,
projectName,
aiven.CreateProjectInvitationRequest{
UserEmail: email,
MemberType: d.Get("member_type").(string),
},
func resourceProjectUserCreate(ctx context.Context, d *schema.ResourceData, client avngen.Client) error {
var (
projectName = d.Get("project").(string)
email = d.Get("email").(string)
memberType = d.Get("member_type").(string)
)

err := client.ProjectInvite(ctx, projectName, &project.ProjectInviteIn{
MemberType: project.MemberType(memberType),
UserEmail: email,
})

if err != nil && !isProjectUserAlreadyInvited(err) {
return diag.FromErr(err)
return err
}

d.SetId(schemautil.BuildResourceID(projectName, email))
if err := d.Set("accepted", false); err != nil {
return diag.FromErr(err)

if err = d.Set("accepted", false); err != nil {
return err
}

return resourceProjectUserRead(ctx, d, m)
return resourceProjectUserRead(ctx, d, client)
}

func resourceProjectUserRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*aiven.Client)

func resourceProjectUserRead(ctx context.Context, d *schema.ResourceData, client avngen.Client) error {
projectName, email, err := schemautil.SplitResourceID2(d.Id())
if err != nil {
return diag.FromErr(err)
return err
}

user, invitation, err := client.ProjectUsers.Get(ctx, projectName, email)
pul, err := client.ProjectUserList(ctx, projectName)
if err != nil {
if aiven.IsNotFound(err) && !d.Get("accepted").(bool) {
return resourceProjectUserCreate(ctx, d, m)
}
return diag.FromErr(schemautil.ResourceReadHandleNotFound(err, d))
return err
}

if err := d.Set("project", projectName); err != nil {
return diag.FromErr(err)
}
if err := d.Set("email", email); err != nil {
return diag.FromErr(err)
}
if user != nil {
if err := d.Set("member_type", user.MemberType); err != nil {
return diag.FromErr(err)
}
if err := d.Set("accepted", true); err != nil {
return diag.FromErr(err)
}
} else {
if err := d.Set("member_type", invitation.MemberType); err != nil {
return diag.FromErr(err)
for _, user := range pul.Users {
if user.UserEmail == email {
if err = d.Set("member_type", string(user.MemberType)); err != nil {
return err
}

if err = d.Set("accepted", true); err != nil {
return err
}

return nil
}
if err := d.Set("accepted", false); err != nil {
return diag.FromErr(err)
}

for _, invitation := range pul.Invitations {
if invitation.InvitedUserEmail == email {
if err = d.Set("member_type", string(invitation.MemberType)); err != nil {
return err
}

if err = d.Set("accepted", false); err != nil {
return err
}

return nil
}
}
return nil
}

func resourceProjectUserUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*aiven.Client)
if !d.Get("accepted").(bool) {
return resourceProjectUserCreate(ctx, d, client)
}

return schemautil.ResourceReadHandleNotFound(errors.New("project user not found"), d)
}

func resourceProjectUserUpdate(ctx context.Context, d *schema.ResourceData, client avngen.Client) error {
projectName, email, err := schemautil.SplitResourceID2(d.Id())
if err != nil {
return diag.FromErr(err)
return err
}

memberType := d.Get("member_type").(string)
err = client.ProjectUsers.UpdateUserOrInvitation(
err = client.ProjectUserUpdate(
ctx,
projectName,
email,
aiven.UpdateProjectUserOrInvitationRequest{
MemberType: memberType,
},
&project.ProjectUserUpdateIn{MemberType: project.MemberType(memberType)},
)
if err != nil {
return diag.FromErr(err)

if err == nil {
return resourceProjectUserRead(ctx, d, client)
}

return resourceProjectUserRead(ctx, d, m)
}
if common.IsCritical(err) {
return err
}

func resourceProjectUserDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*aiven.Client)
// if user not found, delete the user invite and re-invite
if err = client.ProjectInviteDelete(ctx, projectName, email); err != nil {
return err
}

if err = client.ProjectInvite(ctx, projectName, &project.ProjectInviteIn{
MemberType: project.MemberType(memberType),
UserEmail: email,
}); err != nil {
return err
}

return resourceProjectUserRead(ctx, d, client)
}

func resourceProjectUserDelete(ctx context.Context, d *schema.ResourceData, client avngen.Client) error {
projectName, email, err := schemautil.SplitResourceID2(d.Id())
if err != nil {
return diag.FromErr(err)
return err
}

user, invitation, err := client.ProjectUsers.Get(ctx, projectName, email)
pul, err := client.ProjectUserList(ctx, projectName)
if err != nil {
return diag.FromErr(err)
return err
}

// delete user if exists
if user != nil {
err := client.ProjectUsers.DeleteUser(ctx, projectName, email)
if err != nil {
var e aiven.Error
if errors.As(err, &e) && e.Status != 404 ||
!strings.Contains(e.Message, "User does not exist") ||
!strings.Contains(e.Message, "User not found") {

return diag.FromErr(err)
for _, user := range pul.Users {
if user.UserEmail == email {
if err = client.ProjectUserRemove(ctx, projectName, email); err != nil {
var e avngen.Error
if errors.As(err, &e) && e.Status != 404 ||
!strings.Contains(e.Message, "User does not exist") ||
!strings.Contains(e.Message, "User not found") {

return err
}
}
}
}

// delete invitation if exists
if invitation != nil {
err := client.ProjectUsers.DeleteInvitation(ctx, projectName, email)
if common.IsCritical(err) {
return diag.FromErr(err)
for _, invitation := range pul.Invitations {
if invitation.InvitedUserEmail == email {
if err = client.ProjectInviteDelete(ctx, projectName, email); common.IsCritical(err) {
return err
}
}
}

return nil
}

// isProjectUserAlreadyInvited return true if user already been invited to the project
func isProjectUserAlreadyInvited(err error) bool {
var e avngen.Error
if errors.As(err, &e) {
if strings.Contains(e.Message, "already been invited to this project") && e.Status == 409 {
return true
}
}

return false
}
38 changes: 21 additions & 17 deletions internal/sdkprovider/service/project/project_user_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,50 @@ package project

import (
"context"
"fmt"

"github.com/aiven/aiven-go-client/v2"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
avngen "github.com/aiven/go-client-codegen"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/aiven/terraform-provider-aiven/internal/common"
"github.com/aiven/terraform-provider-aiven/internal/schemautil"
)

func DatasourceProjectUser() *schema.Resource {
return &schema.Resource{
ReadContext: datasourceProjectUserRead,
ReadContext: common.WithGenClient(datasourceProjectUserRead),
Description: "The Project User data source provides information about the existing Aiven Project User.",
Schema: schemautil.ResourceSchemaAsDatasourceSchema(aivenProjectUserSchema,
"project", "email"),
}
}

func datasourceProjectUserRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*aiven.Client)
func datasourceProjectUserRead(ctx context.Context, d *schema.ResourceData, client avngen.Client) error {
var (
projectName = d.Get("project").(string)
email = d.Get("email").(string)
)

projectName := d.Get("project").(string)
email := d.Get("email").(string)

users, invitations, err := client.ProjectUsers.List(ctx, projectName)
pul, err := client.ProjectUserList(ctx, projectName)
if err != nil {
return diag.FromErr(err)
return err
}
for _, user := range users {
if user.Email == email {

for _, user := range pul.Users {
if user.UserEmail == email {
d.SetId(schemautil.BuildResourceID(projectName, email))
return resourceProjectUserRead(ctx, d, m)

return resourceProjectUserRead(ctx, d, client)
}
}

for _, invitation := range invitations {
if invitation.UserEmail == email {
for _, invitation := range pul.Invitations {
if invitation.InvitedUserEmail == email {
d.SetId(schemautil.BuildResourceID(projectName, email))
return resourceProjectUserRead(ctx, d, m)

return resourceProjectUserRead(ctx, d, client)
}
}

return diag.Errorf("project user %s/%s not found", projectName, email)
return fmt.Errorf("project user %s/%s not found", projectName, email)
}
23 changes: 15 additions & 8 deletions internal/sdkprovider/service/project/project_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"fmt"
"testing"

"github.com/aiven/aiven-go-client/v2"
avngen "github.com/aiven/go-client-codegen"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
Expand Down Expand Up @@ -48,7 +48,10 @@ func TestAccAivenProjectUser_basic(t *testing.T) {
}

func testAccCheckAivenProjectUserResourceDestroy(s *terraform.State) error {
c := acc.GetTestAivenClient()
c, err := acc.GetTestGenAivenClient()
if err != nil {
return fmt.Errorf("error instantiating client: %w", err)
}

ctx := context.Background()

Expand All @@ -63,20 +66,24 @@ func testAccCheckAivenProjectUserResourceDestroy(s *terraform.State) error {
return err
}

p, i, err := c.ProjectUsers.Get(ctx, projectName, email)
pul, err := c.ProjectUserList(ctx, projectName)
if err != nil {
var e aiven.Error
var e avngen.Error
if errors.As(err, &e) && e.Status != 404 && e.Status != 403 {
return err
}
}

if p != nil {
return fmt.Errorf("porject user (%s) still exists", rs.Primary.ID)
for _, user := range pul.Users {
if user.UserEmail == email {
return fmt.Errorf("porject user (%s) still exists", rs.Primary.ID)
}
}

if i != nil {
return fmt.Errorf("porject user invitation (%s) still exists", rs.Primary.ID)
for _, invitation := range pul.Invitations {
if invitation.InvitedUserEmail == email {
return fmt.Errorf("porject user invitation (%s) still exists", rs.Primary.ID)
}
}
}

Expand Down

0 comments on commit 481e1a2

Please sign in to comment.