Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(project_user): replaced client-v2 with avngen #1978

Merged
merged 1 commit into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ nav_order: 1
add `organization:networking:read`, `organization:networking:write`
- Change `aiven_project_user` field `member_type` (enum): add `organization:networking:read`, `organization:networking:write`
- Change `aiven_service_integration_endpoint` field `endpoint_type` (enum): add `external_azure_blob_storage`
- Replaced `aiven-go-client/v2` with `aiven/go-client-codegen` in `project_user` resource/data source

## [4.33.0] - 2025-01-16

Expand Down
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
Loading