From 528bca3465706eafefcd07f829bdb6d03d87fe2c Mon Sep 17 00:00:00 2001 From: beergeek Date: Fri, 10 Sep 2021 07:38:44 +1000 Subject: [PATCH 01/16] Add Organisation and Project invitations --- ...data_source_mongodbatlas_org_invitation.go | 97 +++++++ ..._source_mongodbatlas_project_invitation.go | 97 +++++++ mongodbatlas/provider.go | 4 + .../resource_mongodbatlas_org_invitation.go | 272 +++++++++++++++++ ...esource_mongodbatlas_project_invitation.go | 273 ++++++++++++++++++ website/docs/d/org_invitation.html.markdown | 52 ++++ .../docs/d/project_initiation.html.markdown | 55 ++++ website/docs/r/org_invitation.html.markdown | 71 +++++ .../docs/r/project_invitation.html.markdown | 73 +++++ 9 files changed, 994 insertions(+) create mode 100644 mongodbatlas/data_source_mongodbatlas_org_invitation.go create mode 100644 mongodbatlas/data_source_mongodbatlas_project_invitation.go create mode 100644 mongodbatlas/resource_mongodbatlas_org_invitation.go create mode 100644 mongodbatlas/resource_mongodbatlas_project_invitation.go create mode 100644 website/docs/d/org_invitation.html.markdown create mode 100644 website/docs/d/project_initiation.html.markdown create mode 100644 website/docs/r/org_invitation.html.markdown create mode 100644 website/docs/r/project_invitation.html.markdown diff --git a/mongodbatlas/data_source_mongodbatlas_org_invitation.go b/mongodbatlas/data_source_mongodbatlas_org_invitation.go new file mode 100644 index 0000000000..e20b4b3021 --- /dev/null +++ b/mongodbatlas/data_source_mongodbatlas_org_invitation.go @@ -0,0 +1,97 @@ +package mongodbatlas + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceMongoDBAtlasOrgInvitation() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceMongoDBAtlasOrgInvitationRead, + Schema: map[string]*schema.Schema{ + "org_id": { + Type: schema.TypeString, + Required: true, + }, + "username": { + Type: schema.TypeString, + Required: true, + }, + "invitation_id": { + Type: schema.TypeString, + Required: true, + }, + "expires_at": { + Type: schema.TypeString, + Computed: true, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "inviter_username": { + Type: schema.TypeString, + Computed: true, + }, + "roles": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + } +} + +func dataSourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Get client connection. + conn := meta.(*MongoDBClient).Atlas + orgID := d.Get("org_id").(string) + username := d.Get("username").(string) + invitationID := d.Get("invitation_id").(string) + + orgInvitation, _, err := conn.Organizations.Invitation(ctx, orgID, invitationID) + if err != nil { + return diag.FromErr(fmt.Errorf("error getting Organisation Invitation information: %s", err)) + } + + if err := d.Set("username", orgInvitation.Username); err != nil { + return diag.FromErr(fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("org_id", orgInvitation.GroupID); err != nil { + return diag.FromErr(fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("invitation_id", orgInvitation.ID); err != nil { + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("expires_at", orgInvitation.ExpiresAt); err != nil { + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("created_at", orgInvitation.CreatedAt); err != nil { + return diag.FromErr(fmt.Errorf("error getting `created_at` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("inviter_username", orgInvitation.InviterUsername); err != nil { + return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("roles", orgInvitation.Roles); err != nil { + return diag.FromErr(fmt.Errorf("error getting `roles` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + d.SetId(encodeStateID(map[string]string{ + "username": username, + "org_id": orgID, + "invitation_id": invitationID, + })) + + return nil +} diff --git a/mongodbatlas/data_source_mongodbatlas_project_invitation.go b/mongodbatlas/data_source_mongodbatlas_project_invitation.go new file mode 100644 index 0000000000..efe64b3b50 --- /dev/null +++ b/mongodbatlas/data_source_mongodbatlas_project_invitation.go @@ -0,0 +1,97 @@ +package mongodbatlas + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceMongoDBAtlasProjectInvitation() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceMongoDBAtlasProjectInvitationRead, + Schema: map[string]*schema.Schema{ + "project_id": { + Type: schema.TypeString, + Required: true, + }, + "username": { + Type: schema.TypeString, + Required: true, + }, + "invitation_id": { + Type: schema.TypeString, + Required: true, + }, + "expires_at": { + Type: schema.TypeString, + Computed: true, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "inviter_username": { + Type: schema.TypeString, + Computed: true, + }, + "roles": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + } +} + +func dataSourceMongoDBAtlasProjectInvitationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Get client connection. + conn := meta.(*MongoDBClient).Atlas + projectID := d.Get("project_id").(string) + username := d.Get("username").(string) + invitationID := d.Get("invitation_id").(string) + + projectInvitation, _, err := conn.Projects.Invitation(ctx, projectID, invitationID) + if err != nil { + return diag.FromErr(fmt.Errorf("error getting Project Invitation information: %s", err)) + } + + if err := d.Set("username", projectInvitation.Username); err != nil { + return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("project_id", projectInvitation.GroupID); err != nil { + return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("invitation_id", projectInvitation.ID); err != nil { + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("expires_at", projectInvitation.ExpiresAt); err != nil { + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("created_at", projectInvitation.CreatedAt); err != nil { + return diag.FromErr(fmt.Errorf("error getting `created_at` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("inviter_username", projectInvitation.InviterUsername); err != nil { + return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("roles", projectInvitation.Roles); err != nil { + return diag.FromErr(fmt.Errorf("error getting `roles` for Project Invitation (%s): %s", d.Id(), err)) + } + + d.SetId(encodeStateID(map[string]string{ + "username": username, + "project_id": projectID, + "invitation_id": invitationID, + })) + + return nil +} diff --git a/mongodbatlas/provider.go b/mongodbatlas/provider.go index 6f65ec65ea..76d8510b67 100644 --- a/mongodbatlas/provider.go +++ b/mongodbatlas/provider.go @@ -100,6 +100,8 @@ func Provider() *schema.Provider { "mongodbatlas_data_lakes": dataSourceMongoDBAtlasDataLakes(), "mongodbatlas_event_trigger": dataSourceMongoDBAtlasEventTrigger(), "mongodbatlas_event_triggers": dataSourceMongoDBAtlasEventTriggers(), + "mongodbatlas_project_invitation": dataSourceMongoDBAtlasProjectInvitation(), + "mongodbatlas_org_invitation": dataSourceMongoDBAtlasOrgInvitation(), }, ResourcesMap: map[string]*schema.Resource{ @@ -136,6 +138,8 @@ func Provider() *schema.Provider { "mongodbatlas_data_lake": resourceMongoDBAtlasDataLake(), "mongodbatlas_event_trigger": resourceMongoDBAtlasEventTriggers(), "mongodbatlas_cloud_backup_schedule": resourceMongoDBAtlasCloudBackupSchedule(), + "mongodbatlas_project_invitation": resourceMongoDBAtlasProjectInvitation(), + "mongodbatlas_org_invitation": resourceMongoDBAtlasOrgInvitation(), }, ConfigureContextFunc: providerConfigure, diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go new file mode 100644 index 0000000000..e4ca59d314 --- /dev/null +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -0,0 +1,272 @@ +package mongodbatlas + +import ( + "context" + "fmt" + "net/http" + "regexp" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + matlas "go.mongodb.org/atlas/mongodbatlas" +) + +func resourceMongoDBAtlasOrgInvitation() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceMongoDBAtlasOrgInvitationCreate, + ReadContext: resourceMongoDBAtlasOrgInvitationRead, + DeleteContext: resourceMongoDBAtlasOrgInvitationDelete, + UpdateContext: resourceMongoDBAtlasOrgInvitationUpdate, + Importer: &schema.ResourceImporter{ + StateContext: resourceMongoDBAtlasOrgInvitationImportState, + }, + Schema: map[string]*schema.Schema{ + "org_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "username": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "invitation_id": { + Type: schema.TypeString, + Computed: true, + }, + "expires_at": { + Type: schema.TypeString, + Computed: true, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "roles": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + } +} + +func resourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Get client connection. + conn := meta.(*MongoDBClient).Atlas + ids := decodeStateID(d.Id()) + orgID := ids["org_id"] + username := ids["username"] + invitationID := ids["invitation_id"] + + orgInvitation, resp, err := conn.Organizations.Invitation(context.Background(), orgID, invitationID) + if err != nil { + // case 404 + // deleted in the backend case + if resp != nil && resp.StatusCode == http.StatusNotFound { + d.SetId("") + return nil + } + + return diag.FromErr(fmt.Errorf("error getting Organisation Invitation information: %s", err)) + } + + if err := d.Set("username", orgInvitation.Username); err != nil { + return diag.FromErr(fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("org_id", orgInvitation.GroupID); err != nil { + return diag.FromErr(fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("invitation_id", orgInvitation.ID); err != nil { + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("expires_at", orgInvitation.ExpiresAt); err != nil { + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("created_at", orgInvitation.CreatedAt); err != nil { + return diag.FromErr(fmt.Errorf("error getting `created_at` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("roles", orgInvitation.Roles); err != nil { + return diag.FromErr(fmt.Errorf("error getting `roles` for Organisation Invitation (%s): %s", d.Id(), err)) + } + + d.SetId(encodeStateID(map[string]string{ + "username": username, + "org_id": orgID, + "invitation_id": invitationID, + })) + + return nil +} + +func resourceMongoDBAtlasOrgInvitationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Get client connection. + conn := meta.(*MongoDBClient).Atlas + orgID := d.Get("org_id").(string) + + err := validateOrgRoles(d.Get("roles").(*schema.Set)) + if err != nil { + return diag.FromErr(err) + } + + InvitationReq := &matlas.Invitation{ + Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), + Username: d.Get("username").(string), + } + + InvitationRes, resp, err := conn.Organizations.InviteUser(ctx, orgID, InvitationReq) + if err != nil { + // case 404 + // deleted in the backend case + if resp != nil && resp.StatusCode == http.StatusNotFound { + d.SetId("") + return nil + } + return diag.FromErr(fmt.Errorf("error creating Organisation invitation: %s", err)) + } + + d.SetId(encodeStateID(map[string]string{ + "username": InvitationRes.Username, + "org_id": InvitationRes.OrgID, + "invitation_id": InvitationRes.ID, + })) + + return resourceMongoDBAtlasOrgInvitationRead(ctx, d, meta) +} + +func resourceMongoDBAtlasOrgInvitationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*MongoDBClient).Atlas + ids := decodeStateID(d.Id()) + orgID := ids["org_id"] + username := ids["username"] + invitationID := ids["invitation_id"] + + _, err := conn.Organizations.DeleteInvitation(ctx, orgID, invitationID) + if err != nil { + return diag.FromErr(fmt.Errorf("error creating Organisation invitation: %s for %s", username, err)) + } + + return nil +} + +func resourceMongoDBAtlasOrgInvitationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*MongoDBClient).Atlas + ids := decodeStateID(d.Id()) + orgID := ids["org_id"] + username := ids["username"] + invitationID := ids["invitation_id"] + + InvitationReq := &matlas.Invitation{ + Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), + } + + _, _, err := conn.Organizations.UpdateInvitationByID(ctx, orgID, invitationID, InvitationReq) + if err != nil { + return diag.FromErr(fmt.Errorf("error creating Organisation invitation: %s for %s", username, err)) + } + + return resourceMongoDBAtlasOrgInvitationRead(ctx, d, meta) +} + +func resourceMongoDBAtlasOrgInvitationImportState(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + conn := meta.(*MongoDBClient).Atlas + orgID, username, err := splitProjectInvitationImportID(d.Id()) + if err != nil { + return nil, err + } + + orgInvitations, _, err := conn.Organizations.Invitations(ctx, orgID, nil) + if err != nil { + return nil, fmt.Errorf("couldn't import Organisation invitations, error: %s", err) + } + + for _, orgInvitation := range orgInvitations { + if orgInvitation.Username == username { + + if err := d.Set("username", orgInvitation.Username); err != nil { + return nil, fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", username, err) + } + + if err := d.Set("org_id", orgInvitation.GroupID); err != nil { + return nil, fmt.Errorf("error getting `org_id` for Organisation Invitation (%s): %s", username, err) + } + + if err := d.Set("invitation_id", orgInvitation.ID); err != nil { + return nil, fmt.Errorf("error getting `invitation_id` for Organisation Invitation (%s): %s", username, err) + } + + d.SetId(encodeStateID(map[string]string{ + "username": username, + "org_id": orgID, + "invitation_id": orgInvitation.ID, + })) + + return []*schema.ResourceData{d}, nil + } + } + + return nil, fmt.Errorf("Could not import Organisation Invitation for %s", d.Id()) +} + +func splitOrgInvitationImportID(id string) (orgID, username string, err error) { + var re = regexp.MustCompile(`(?s)^([0-9a-fA-F]{24})-(.*)$`) + parts := re.FindStringSubmatch(id) + + if len(parts) != 3 { + err = fmt.Errorf("import format error: to import a Organisation Invitation, use the format {project_id}-{username}") + return + } + + orgID = parts[1] + username = parts[2] + + return +} + +func validateOrgRoles(list *schema.Set) error { + if rs := list.List(); list.Len() > 0 { + for _, role := range rs { + if validateOrgRole(role.(string)) == false { + return fmt.Errorf("error creating an invite: %s is an invalid role for a Organisation", role) + } + } + } + + return nil +} + +func validateOrgRole(str string) bool { + org_roles := []string{ + "ORG_OWNER", + "ORG_GROUP_CREATOR", + "ORG_BILLING_ADMIN", + "ORG_READ_ONLY", + "ORG_MEMBER", + } + + for _, valid_role := range org_roles { + if valid_role == str { + return true + } + } + + return false +} + +func createOrgStringListFromSetSchema(list *schema.Set) []string { + res := make([]string, list.Len()) + for i, v := range list.List() { + res[i] = v.(string) + } + + return res +} diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation.go b/mongodbatlas/resource_mongodbatlas_project_invitation.go new file mode 100644 index 0000000000..1bbb97de0e --- /dev/null +++ b/mongodbatlas/resource_mongodbatlas_project_invitation.go @@ -0,0 +1,273 @@ +package mongodbatlas + +import ( + "context" + "fmt" + "net/http" + "regexp" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + matlas "go.mongodb.org/atlas/mongodbatlas" +) + +func resourceMongoDBAtlasProjectInvitation() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceMongoDBAtlasProjectInvitationCreate, + ReadContext: resourceMongoDBAtlasProjectInvitationRead, + DeleteContext: resourceMongoDBAtlasProjectInvitationDelete, + UpdateContext: resourceMongoDBAtlasProjectInvitationUpdate, + Importer: &schema.ResourceImporter{ + StateContext: resourceMongoDBAtlasProjectInvitationImportState, + }, + Schema: map[string]*schema.Schema{ + "project_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "username": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "invitation_id": { + Type: schema.TypeString, + Computed: true, + }, + "expires_at": { + Type: schema.TypeString, + Computed: true, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "roles": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + } +} + +func resourceMongoDBAtlasProjectInvitationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Get client connection. + conn := meta.(*MongoDBClient).Atlas + ids := decodeStateID(d.Id()) + projectID := ids["project_id"] + username := ids["username"] + invitationID := ids["invitation_id"] + + projectInvitation, resp, err := conn.Projects.Invitation(context.Background(), projectID, invitationID) + if err != nil { + // case 404 + // deleted in the backend case + if resp != nil && resp.StatusCode == http.StatusNotFound { + d.SetId("") + return nil + } + + return diag.FromErr(fmt.Errorf("error getting Project Invitation information: %s", err)) + } + + if err := d.Set("username", projectInvitation.Username); err != nil { + return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("project_id", projectInvitation.GroupID); err != nil { + return diag.FromErr(fmt.Errorf("error getting `project_id` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("invitation_id", projectInvitation.ID); err != nil { + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("expires_at", projectInvitation.ExpiresAt); err != nil { + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("created_at", projectInvitation.CreatedAt); err != nil { + return diag.FromErr(fmt.Errorf("error getting `created_at` for Project Invitation (%s): %s", d.Id(), err)) + } + + if err := d.Set("roles", projectInvitation.Roles); err != nil { + return diag.FromErr(fmt.Errorf("error getting `roles` for Project Invitation (%s): %s", d.Id(), err)) + } + + d.SetId(encodeStateID(map[string]string{ + "username": username, + "project_id": projectID, + "invitation_id": invitationID, + })) + + return nil +} + +func resourceMongoDBAtlasProjectInvitationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Get client connection. + conn := meta.(*MongoDBClient).Atlas + projectID := d.Get("project_id").(string) + + err := validateProjectRoles(d.Get("roles").(*schema.Set)) + if err != nil { + return diag.FromErr(err) + } + + InvitationReq := &matlas.Invitation{ + Roles: createProjectStringListFromSetSchema(d.Get("roles").(*schema.Set)), + Username: d.Get("username").(string), + } + + InvitationRes, resp, err := conn.Projects.InviteUser(ctx, projectID, InvitationReq) + if err != nil { + // case 404 + // deleted in the backend case + if resp != nil && resp.StatusCode == http.StatusNotFound { + d.SetId("") + return nil + } + return diag.FromErr(fmt.Errorf("error creating Atlas user: %s", err)) + } + + d.SetId(encodeStateID(map[string]string{ + "username": InvitationRes.Username, + "project_id": InvitationRes.GroupID, + "invitation_id": InvitationRes.ID, + })) + + return resourceMongoDBAtlasProjectInvitationRead(ctx, d, meta) +} + +func resourceMongoDBAtlasProjectInvitationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*MongoDBClient).Atlas + ids := decodeStateID(d.Id()) + projectID := ids["project_id"] + username := ids["username"] + invitationID := ids["invitation_id"] + + _, err := conn.Projects.DeleteInvitation(ctx, projectID, invitationID) + if err != nil { + return diag.FromErr(fmt.Errorf("error creating Project invitation: %s for %s", username, err)) + } + + return nil +} + +func resourceMongoDBAtlasProjectInvitationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*MongoDBClient).Atlas + ids := decodeStateID(d.Id()) + projectID := ids["project_id"] + username := ids["username"] + invitationID := ids["invitation_id"] + + InvitationReq := &matlas.Invitation{ + Roles: createProjectStringListFromSetSchema(d.Get("roles").(*schema.Set)), + } + + _, _, err := conn.Projects.UpdateInvitationByID(ctx, projectID, invitationID, InvitationReq) + if err != nil { + return diag.FromErr(fmt.Errorf("error creating Project invitation: %s for %s", username, err)) + } + + return resourceMongoDBAtlasProjectInvitationRead(ctx, d, meta) +} + +func resourceMongoDBAtlasProjectInvitationImportState(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + conn := meta.(*MongoDBClient).Atlas + projectID, username, err := splitProjectInvitationImportID(d.Id()) + if err != nil { + return nil, err + } + + projectInvitations, _, err := conn.Projects.Invitations(ctx, projectID, nil) + if err != nil { + return nil, fmt.Errorf("couldn't import Project invitations, error: %s", err) + } + + for _, projectInvitation := range projectInvitations { + if projectInvitation.Username == username { + + if err := d.Set("username", projectInvitation.Username); err != nil { + return nil, fmt.Errorf("error getting `username` for Project Invitation (%s): %s", username, err) + } + + if err := d.Set("project_id", projectInvitation.GroupID); err != nil { + return nil, fmt.Errorf("error getting `project_id` for Project Invitation (%s): %s", username, err) + } + + if err := d.Set("invitation_id", projectInvitation.ID); err != nil { + return nil, fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %s", username, err) + } + + d.SetId(encodeStateID(map[string]string{ + "username": username, + "project_id": projectID, + "invitation_id": projectInvitation.ID, + })) + + return []*schema.ResourceData{d}, nil + } + } + + return nil, fmt.Errorf("Could not import Project Invitation for %s", d.Id()) +} + +func splitProjectInvitationImportID(id string) (projectID, username string, err error) { + var re = regexp.MustCompile(`(?s)^([0-9a-fA-F]{24})-(.*)$`) + parts := re.FindStringSubmatch(id) + + if len(parts) != 3 { + err = fmt.Errorf("import format error: to import a Project Invitation, use the format {project_id}-{username}") + return + } + + projectID = parts[1] + username = parts[2] + + return +} + +func validateProjectRoles(list *schema.Set) error { + if rs := list.List(); list.Len() > 0 { + for _, role := range rs { + if validateProjectRole(role.(string)) == false { + return fmt.Errorf("error creating an invite: %s is an invalid role for a Project", role) + } + } + } + + return nil +} + +func validateProjectRole(str string) bool { + proj_roles := []string{ + "GROUP_OWNER", + "GROUP_CLUSTER_MANAGER", + "GROUP_READ_ONLY", + "GROUP_DATA_ACCESS_ADMIN", + "GROUP_DATA_ACCESS_READ_WRITE", + "GROUP_DATA_ACCESS_READ_ONLY", + } + + for _, valid_role := range proj_roles { + if valid_role == str { + return true + } + } + + return false +} + +func createProjectStringListFromSetSchema(list *schema.Set) []string { + res := make([]string, list.Len()) + for i, v := range list.List() { + res[i] = v.(string) + } + + return res +} diff --git a/website/docs/d/org_invitation.html.markdown b/website/docs/d/org_invitation.html.markdown new file mode 100644 index 0000000000..76e07cd734 --- /dev/null +++ b/website/docs/d/org_invitation.html.markdown @@ -0,0 +1,52 @@ +--- +layout: "mongodbatlas" +page_title: "MongoDB Atlas: org_invitation" +sidebar_current: "docs-mongodbatlas-organisation-invitation" +description: |- + Provides a Atlas Organisation Invitation resource. +--- + +# mongodbatlas_database_user + +`mongodbatlas_org_invitation` describes a Organisation Invitation resource. This represents an invitation for an Atlas User within an Atlas Organisation. + +Each invitation has a set of roles for an Atlas user within an organisation. + +-> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. + +## Example Usage + +```hcl +resource "mongodbatlas_org_invitation" "test" { + username = "test-acc-username" + org_id = "" + roles = [ "GROUP_DATA_ACCESS_READ_WRITE" ] +} + +data "mongodbatlas_org_user" "test" { + org_id = mongodbatlas_org_user.test.org_id + username = mongodbatlas_org_user.test.username +} +``` + +## Argument Reference + +* `org_id` - (Required) The unique ID for the project to create the database user. +* `username` - (Required) The Atlas user's email address. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The database user's name. +* `created_at` - The date and time the invitation was created +* `expires_at` - The date and time that the invitation will expire +* `invitation_id` - The identify of the invitation in Atlas +* `roles` - List of user’s Atlas roles. The available options are: + * ORG_OWNER + * ORG_GROUP_CREATOR + * ORG_BILLING_ADMIN + * ORG_READ_ONLY + * ORG_MEMBER + +See [MongoDB Atlas API](https://docs.atlas.mongodb.com/reference/api/organization-get-one-invitation/) Documentation for more information. \ No newline at end of file diff --git a/website/docs/d/project_initiation.html.markdown b/website/docs/d/project_initiation.html.markdown new file mode 100644 index 0000000000..9ffc7bc0cb --- /dev/null +++ b/website/docs/d/project_initiation.html.markdown @@ -0,0 +1,55 @@ +--- +layout: "mongodbatlas" +page_title: "MongoDB Atlas: project_invitation" +sidebar_current: "docs-mongodbatlas-project-invitation" +description: |- + Provides a Atlas Project Invitation resource. +--- + +# mongodbatlas_project_invitation + +`mongodbatlas_project_invitation` describes a Project Invitation resource. This represents an invitation for an Atlas User within an Atlas Project. + +Each invitation for an Atlas user has a set of roles that provide access to a project in an organisation. + +-> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. + +~> **IMPORTANT:** All arguments including the password will be stored in the raw state as plain-text. [Read more about sensitive data in state.](https://www.terraform.io/docs/state/sensitive-data.html) + +## Example Usages + +```hcl +resource "mongodbatlas_project_invitation" "test" { + username = "test-acc-username" + project_id = "" + roles = [ "GROUP_DATA_ACCESS_READ_WRITE" ] +} + +data "mongodbatlas_project_invitation" "test" { + project_id = mongodbatlas_project_invitation.test.project_id + username = mongodbatlas_project_invitation.test.username +} +``` + +## Argument Reference + +* `project_id` - (Required) The unique ID for the project to create the database user. +* `username` - (Required) The Atlas user's email address. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The database user's name. +* `created_at` - The date and time the invitation was created +* `expires_at` - The date and time that the invitation will expire +* `invitation_id` - The identify of the invitation in Atlas +* `roles` - List of user’s roles within the Atlas project. The available options are: + * GROUP_OWNER + * GROUP_CLUSTER_MANAGER + * GROUP_READ_ONLY + * GROUP_DATA_ACCESS_ADMIN + * GROUP_DATA_ACCESS_READ_WRITE + * GROUP_DATA_ACCESS_READ_ONLY + +See [MongoDB Atlas API](https://docs.atlas.mongodb.com/reference/user-roles/#project-roles) Documentation for more information. \ No newline at end of file diff --git a/website/docs/r/org_invitation.html.markdown b/website/docs/r/org_invitation.html.markdown new file mode 100644 index 0000000000..7fc739c503 --- /dev/null +++ b/website/docs/r/org_invitation.html.markdown @@ -0,0 +1,71 @@ +--- +layout: "mongodbatlas" +page_title: "MongoDB Atlas: org_invitation" +sidebar_current: "docs-mongodbatlas-organisation-invitation" +description: |- + Provides a Atlas Organisation Invitation resource. +--- + +# mongodbatlas_org_invitation + +`mongodbatlas_org_invitation` provides a Organisation Invitation resource. This represents an invitation for an Atlas User within an Atlas Organisation. + +Each invitation for an Atlas user has a set of roles that provide access to an organisation. + +The roles that can be utilised can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#organization-roles), which map to: + +* ORG_OWNER +* ORG_GROUP_CREATOR +* ORG_BILLING_ADMIN +* ORG_READ_ONLY +* ORG_MEMBER + +-> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. + +~> **IMPORTANT:** All arguments including the password will be stored in the raw state as plain-text. [Read more about sensitive data in state.](https://www.terraform.io/docs/state/sensitive-data.html) + +## Example Usages + +```hcl +resource "mongodbatlas_org_invitation" "test" { + username = "test-acc-username" + org_id = "" + roles = [ "GROUP_DATA_ACCESS_READ_WRITE" ] +} +``` + +```hcl +resource "mongodbatlas_org_invitation" "test" { + username = "test-acc-username" + org_id = "" + roles = [ "GROUP_READ_ONLY", "GROUP_DATA_ACCESS_READ_ONLY" ] +} +``` + +## Argument Reference + +* `project_id` - (Required) The unique ID for the project to create the database user. +* `username` - (Required) The Atlas user's email address. +* `roles` - (Required) List of user’s Atlas roles. The available options are: + * ORG_OWNER + * ORG_GROUP_CREATOR + * ORG_BILLING_ADMIN + * ORG_READ_ONLY + * ORG_MEMBER + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The database user's name. +* `created_at` - The date and time the invitation was created +* `expires_at` - The date and time that the invitation will expire +* `invitation_id` - The identify of the invitation in Atlas + +## Import + +Organisations Invitations can be imported using organisation ID and username (email address), in the format `org_id`-`username`, e.g. + +``` +$ terraform import mongodbatlas_org_invitation.my_user 1112222b3bf99403840e8934-my_user +``` diff --git a/website/docs/r/project_invitation.html.markdown b/website/docs/r/project_invitation.html.markdown new file mode 100644 index 0000000000..071e4fa9a2 --- /dev/null +++ b/website/docs/r/project_invitation.html.markdown @@ -0,0 +1,73 @@ +--- +layout: "mongodbatlas" +page_title: "MongoDB Atlas: project_invitation" +sidebar_current: "docs-mongodbatlas-resource-project-invitation" +description: |- + Provides a Atlas Project Invitation resource. +--- + +# mongodbatlas_project_invitation + +`mongodbatlas_project_invitation` provides a Project Invitation resource. This represents an invitation for an Atlas User within an Atlas Project. + +Each invitation for an Atlas user has a set of roles that provide access to a project in an organisation. + +The roles that can be utilised can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#project-roles), which map to: + +* GROUP_OWNER +* GROUP_CLUSTER_MANAGER +* GROUP_READ_ONLY +* GROUP_DATA_ACCESS_ADMIN +* GROUP_DATA_ACCESS_READ_WRITE +* GROUP_DATA_ACCESS_READ_ONLY + +-> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. + +~> **IMPORTANT:** All arguments including the password will be stored in the raw state as plain-text. [Read more about sensitive data in state.](https://www.terraform.io/docs/state/sensitive-data.html) + +## Example Usages + +```hcl +resource "mongodbatlas_project_invitation" "test" { + username = "test-acc-username" + project_id = "" + roles = [ "GROUP_DATA_ACCESS_READ_WRITE" ] +} +``` + +```hcl +resource "mongodbatlas_project_invitation" "test" { + username = "test-acc-username" + project_id = "" + roles = [ "GROUP_READ_ONLY", "GROUP_DATA_ACCESS_READ_ONLY" ] +} +``` + +## Argument Reference + +* `project_id` - (Required) The unique ID for the project to create the database user. +* `username` - (Required) The Atlas user's email address. +* `roles` - (Required) List of user’s roles within the Atlas project. The available options are: + * GROUP_OWNER + * GROUP_CLUSTER_MANAGER + * GROUP_READ_ONLY + * GROUP_DATA_ACCESS_ADMIN + * GROUP_DATA_ACCESS_READ_WRITE + * GROUP_DATA_ACCESS_READ_ONLY + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The database user's name. +* `created_at` - The date and time the invitation was created +* `expires_at` - The date and time that the invitation will expire +* `invitation_id` - The identify of the invitation in Atlas + +## Import + +Projects Invitations can be imported using project ID and username (email address), in the format `project_id`-`username`, e.g. + +``` +$ terraform import mongodbatlas_project_invitation.my_user 1112222b3bf99403840e8934-my_user +``` From cb083f410a8bd3df367c46c2007102a94cb8d44e Mon Sep 17 00:00:00 2001 From: beergeek Date: Fri, 10 Sep 2021 09:25:51 +1000 Subject: [PATCH 02/16] Fix linting issues --- ...data_source_mongodbatlas_org_invitation.go | 16 ++-- .../resource_mongodbatlas_org_invitation.go | 75 +++++++++---------- ...esource_mongodbatlas_project_invitation.go | 47 ++++++------ 3 files changed, 66 insertions(+), 72 deletions(-) diff --git a/mongodbatlas/data_source_mongodbatlas_org_invitation.go b/mongodbatlas/data_source_mongodbatlas_org_invitation.go index e20b4b3021..18eb4b0559 100644 --- a/mongodbatlas/data_source_mongodbatlas_org_invitation.go +++ b/mongodbatlas/data_source_mongodbatlas_org_invitation.go @@ -56,35 +56,35 @@ func dataSourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Reso orgInvitation, _, err := conn.Organizations.Invitation(ctx, orgID, invitationID) if err != nil { - return diag.FromErr(fmt.Errorf("error getting Organisation Invitation information: %s", err)) + return diag.FromErr(fmt.Errorf("error getting Organization Invitation information: %s", err)) } if err := d.Set("username", orgInvitation.Username); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("org_id", orgInvitation.GroupID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("invitation_id", orgInvitation.ID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("expires_at", orgInvitation.ExpiresAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("created_at", orgInvitation.CreatedAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `created_at` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `created_at` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("inviter_username", orgInvitation.InviterUsername); err != nil { - return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("roles", orgInvitation.Roles); err != nil { - return diag.FromErr(fmt.Errorf("error getting `roles` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `roles` for Organization Invitation (%s): %s", d.Id(), err)) } d.SetId(encodeStateID(map[string]string{ diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index e4ca59d314..2fb8d1d057 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -72,31 +72,31 @@ func resourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Resour return nil } - return diag.FromErr(fmt.Errorf("error getting Organisation Invitation information: %s", err)) + return diag.FromErr(fmt.Errorf("error getting Organization Invitation information: %s", err)) } if err := d.Set("username", orgInvitation.Username); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("org_id", orgInvitation.GroupID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("invitation_id", orgInvitation.ID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("expires_at", orgInvitation.ExpiresAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("created_at", orgInvitation.CreatedAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `created_at` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `created_at` for Organization Invitation (%s): %s", d.Id(), err)) } if err := d.Set("roles", orgInvitation.Roles); err != nil { - return diag.FromErr(fmt.Errorf("error getting `roles` for Organisation Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `roles` for Organization Invitation (%s): %s", d.Id(), err)) } d.SetId(encodeStateID(map[string]string{ @@ -131,7 +131,7 @@ func resourceMongoDBAtlasOrgInvitationCreate(ctx context.Context, d *schema.Reso d.SetId("") return nil } - return diag.FromErr(fmt.Errorf("error creating Organisation invitation: %s", err)) + return diag.FromErr(fmt.Errorf("error creating Organization invitation: %s", err)) } d.SetId(encodeStateID(map[string]string{ @@ -152,7 +152,7 @@ func resourceMongoDBAtlasOrgInvitationDelete(ctx context.Context, d *schema.Reso _, err := conn.Organizations.DeleteInvitation(ctx, orgID, invitationID) if err != nil { - return diag.FromErr(fmt.Errorf("error creating Organisation invitation: %s for %s", username, err)) + return diag.FromErr(fmt.Errorf("error creating Organization invitation: %s for %s", username, err)) } return nil @@ -171,7 +171,7 @@ func resourceMongoDBAtlasOrgInvitationUpdate(ctx context.Context, d *schema.Reso _, _, err := conn.Organizations.UpdateInvitationByID(ctx, orgID, invitationID, InvitationReq) if err != nil { - return diag.FromErr(fmt.Errorf("error creating Organisation invitation: %s for %s", username, err)) + return diag.FromErr(fmt.Errorf("error creating Organization invitation: %s for %s", username, err)) } return resourceMongoDBAtlasOrgInvitationRead(ctx, d, meta) @@ -179,42 +179,39 @@ func resourceMongoDBAtlasOrgInvitationUpdate(ctx context.Context, d *schema.Reso func resourceMongoDBAtlasOrgInvitationImportState(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { conn := meta.(*MongoDBClient).Atlas - orgID, username, err := splitProjectInvitationImportID(d.Id()) + orgID, username, err := splitOrgInvitationImportID(d.Id()) if err != nil { return nil, err } orgInvitations, _, err := conn.Organizations.Invitations(ctx, orgID, nil) if err != nil { - return nil, fmt.Errorf("couldn't import Organisation invitations, error: %s", err) + return nil, fmt.Errorf("couldn't import Organization invitations, error: %s", err) } for _, orgInvitation := range orgInvitations { - if orgInvitation.Username == username { - - if err := d.Set("username", orgInvitation.Username); err != nil { - return nil, fmt.Errorf("error getting `username` for Organisation Invitation (%s): %s", username, err) - } - - if err := d.Set("org_id", orgInvitation.GroupID); err != nil { - return nil, fmt.Errorf("error getting `org_id` for Organisation Invitation (%s): %s", username, err) - } - - if err := d.Set("invitation_id", orgInvitation.ID); err != nil { - return nil, fmt.Errorf("error getting `invitation_id` for Organisation Invitation (%s): %s", username, err) - } - - d.SetId(encodeStateID(map[string]string{ - "username": username, - "org_id": orgID, - "invitation_id": orgInvitation.ID, - })) + if orgInvitation.Username != username { + continue + } - return []*schema.ResourceData{d}, nil + if err := d.Set("username", orgInvitation.Username); err != nil { + return nil, fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", username, err) + } + if err := d.Set("org_id", orgInvitation.GroupID); err != nil { + return nil, fmt.Errorf("error getting `org_id` for Organization Invitation (%s): %s", username, err) + } + if err := d.Set("invitation_id", orgInvitation.ID); err != nil { + return nil, fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %s", username, err) } + d.SetId(encodeStateID(map[string]string{ + "username": username, + "org_id": orgID, + "invitation_id": orgInvitation.ID, + })) + return []*schema.ResourceData{d}, nil } - return nil, fmt.Errorf("Could not import Organisation Invitation for %s", d.Id()) + return nil, fmt.Errorf("could not import Organization Invitation for %s", d.Id()) } func splitOrgInvitationImportID(id string) (orgID, username string, err error) { @@ -222,7 +219,7 @@ func splitOrgInvitationImportID(id string) (orgID, username string, err error) { parts := re.FindStringSubmatch(id) if len(parts) != 3 { - err = fmt.Errorf("import format error: to import a Organisation Invitation, use the format {project_id}-{username}") + err = fmt.Errorf("import format error: to import a Organization Invitation, use the format {project_id}-{username}") return } @@ -235,8 +232,8 @@ func splitOrgInvitationImportID(id string) (orgID, username string, err error) { func validateOrgRoles(list *schema.Set) error { if rs := list.List(); list.Len() > 0 { for _, role := range rs { - if validateOrgRole(role.(string)) == false { - return fmt.Errorf("error creating an invite: %s is an invalid role for a Organisation", role) + if !validateOrgRole(role.(string)) { + return fmt.Errorf("error creating an invite: %s is an invalid role for a Organization", role) } } } @@ -245,7 +242,7 @@ func validateOrgRoles(list *schema.Set) error { } func validateOrgRole(str string) bool { - org_roles := []string{ + orgRoles := []string{ "ORG_OWNER", "ORG_GROUP_CREATOR", "ORG_BILLING_ADMIN", @@ -253,8 +250,8 @@ func validateOrgRole(str string) bool { "ORG_MEMBER", } - for _, valid_role := range org_roles { - if valid_role == str { + for _, validRole := range orgRoles { + if validRole == str { return true } } diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation.go b/mongodbatlas/resource_mongodbatlas_project_invitation.go index 1bbb97de0e..7e26dd94c4 100644 --- a/mongodbatlas/resource_mongodbatlas_project_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_project_invitation.go @@ -190,31 +190,28 @@ func resourceMongoDBAtlasProjectInvitationImportState(ctx context.Context, d *sc } for _, projectInvitation := range projectInvitations { - if projectInvitation.Username == username { - - if err := d.Set("username", projectInvitation.Username); err != nil { - return nil, fmt.Errorf("error getting `username` for Project Invitation (%s): %s", username, err) - } - - if err := d.Set("project_id", projectInvitation.GroupID); err != nil { - return nil, fmt.Errorf("error getting `project_id` for Project Invitation (%s): %s", username, err) - } - - if err := d.Set("invitation_id", projectInvitation.ID); err != nil { - return nil, fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %s", username, err) - } - - d.SetId(encodeStateID(map[string]string{ - "username": username, - "project_id": projectID, - "invitation_id": projectInvitation.ID, - })) + if projectInvitation.Username != username { + continue + } - return []*schema.ResourceData{d}, nil + if err := d.Set("username", projectInvitation.Username); err != nil { + return nil, fmt.Errorf("error getting `username` for Project Invitation (%s): %s", username, err) + } + if err := d.Set("project_id", projectInvitation.GroupID); err != nil { + return nil, fmt.Errorf("error getting `project_id` for Project Invitation (%s): %s", username, err) + } + if err := d.Set("invitation_id", projectInvitation.ID); err != nil { + return nil, fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %s", username, err) } + d.SetId(encodeStateID(map[string]string{ + "username": username, + "project_id": projectID, + "invitation_id": projectInvitation.ID, + })) + return []*schema.ResourceData{d}, nil } - return nil, fmt.Errorf("Could not import Project Invitation for %s", d.Id()) + return nil, fmt.Errorf("could not import Project Invitation for %s", d.Id()) } func splitProjectInvitationImportID(id string) (projectID, username string, err error) { @@ -235,7 +232,7 @@ func splitProjectInvitationImportID(id string) (projectID, username string, err func validateProjectRoles(list *schema.Set) error { if rs := list.List(); list.Len() > 0 { for _, role := range rs { - if validateProjectRole(role.(string)) == false { + if !validateProjectRole(role.(string)) { return fmt.Errorf("error creating an invite: %s is an invalid role for a Project", role) } } @@ -245,7 +242,7 @@ func validateProjectRoles(list *schema.Set) error { } func validateProjectRole(str string) bool { - proj_roles := []string{ + projRoles := []string{ "GROUP_OWNER", "GROUP_CLUSTER_MANAGER", "GROUP_READ_ONLY", @@ -254,8 +251,8 @@ func validateProjectRole(str string) bool { "GROUP_DATA_ACCESS_READ_ONLY", } - for _, valid_role := range proj_roles { - if valid_role == str { + for _, validRole := range projRoles { + if validRole == str { return true } } From 7c007fd940be0efe3114ade3c9d99048d4f73c0b Mon Sep 17 00:00:00 2001 From: beergeek Date: Sat, 11 Sep 2021 11:18:20 +1000 Subject: [PATCH 03/16] Change to American spelling --- website/docs/d/org_invitation.html.markdown | 4 ++-- website/docs/d/project_initiation.html.markdown | 2 +- website/docs/r/org_invitation.html.markdown | 6 +++--- website/docs/r/project_invitation.html.markdown | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/website/docs/d/org_invitation.html.markdown b/website/docs/d/org_invitation.html.markdown index 76e07cd734..5ba794933a 100644 --- a/website/docs/d/org_invitation.html.markdown +++ b/website/docs/d/org_invitation.html.markdown @@ -1,7 +1,7 @@ --- layout: "mongodbatlas" page_title: "MongoDB Atlas: org_invitation" -sidebar_current: "docs-mongodbatlas-organisation-invitation" +sidebar_current: "docs-mongodbatlas-organization-invitation" description: |- Provides a Atlas Organisation Invitation resource. --- @@ -10,7 +10,7 @@ description: |- `mongodbatlas_org_invitation` describes a Organisation Invitation resource. This represents an invitation for an Atlas User within an Atlas Organisation. -Each invitation has a set of roles for an Atlas user within an organisation. +Each invitation has a set of roles for an Atlas user within an organization. -> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. diff --git a/website/docs/d/project_initiation.html.markdown b/website/docs/d/project_initiation.html.markdown index 9ffc7bc0cb..da7d86df03 100644 --- a/website/docs/d/project_initiation.html.markdown +++ b/website/docs/d/project_initiation.html.markdown @@ -10,7 +10,7 @@ description: |- `mongodbatlas_project_invitation` describes a Project Invitation resource. This represents an invitation for an Atlas User within an Atlas Project. -Each invitation for an Atlas user has a set of roles that provide access to a project in an organisation. +Each invitation for an Atlas user has a set of roles that provide access to a project in an organization. -> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. diff --git a/website/docs/r/org_invitation.html.markdown b/website/docs/r/org_invitation.html.markdown index 7fc739c503..84ccd0277d 100644 --- a/website/docs/r/org_invitation.html.markdown +++ b/website/docs/r/org_invitation.html.markdown @@ -1,7 +1,7 @@ --- layout: "mongodbatlas" page_title: "MongoDB Atlas: org_invitation" -sidebar_current: "docs-mongodbatlas-organisation-invitation" +sidebar_current: "docs-mongodbatlas-organization-invitation" description: |- Provides a Atlas Organisation Invitation resource. --- @@ -10,7 +10,7 @@ description: |- `mongodbatlas_org_invitation` provides a Organisation Invitation resource. This represents an invitation for an Atlas User within an Atlas Organisation. -Each invitation for an Atlas user has a set of roles that provide access to an organisation. +Each invitation for an Atlas user has a set of roles that provide access to an organization. The roles that can be utilised can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#organization-roles), which map to: @@ -64,7 +64,7 @@ In addition to all arguments above, the following attributes are exported: ## Import -Organisations Invitations can be imported using organisation ID and username (email address), in the format `org_id`-`username`, e.g. +Organisations Invitations can be imported using organization ID and username (email address), in the format `org_id`-`username`, e.g. ``` $ terraform import mongodbatlas_org_invitation.my_user 1112222b3bf99403840e8934-my_user diff --git a/website/docs/r/project_invitation.html.markdown b/website/docs/r/project_invitation.html.markdown index 071e4fa9a2..9104903575 100644 --- a/website/docs/r/project_invitation.html.markdown +++ b/website/docs/r/project_invitation.html.markdown @@ -10,7 +10,7 @@ description: |- `mongodbatlas_project_invitation` provides a Project Invitation resource. This represents an invitation for an Atlas User within an Atlas Project. -Each invitation for an Atlas user has a set of roles that provide access to a project in an organisation. +Each invitation for an Atlas user has a set of roles that provide access to a project in an organization. The roles that can be utilised can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#project-roles), which map to: From 4bb4e639d028a15a7a80f9328453b894b2ba75f4 Mon Sep 17 00:00:00 2001 From: beergeek Date: Tue, 14 Sep 2021 20:25:08 +1000 Subject: [PATCH 04/16] Apply fixes and suggested modifications --- ...data_source_mongodbatlas_org_invitation.go | 16 ++--- ..._source_mongodbatlas_project_invitation.go | 14 ++--- .../resource_mongodbatlas_org_invitation.go | 58 ++++++++++--------- ...esource_mongodbatlas_project_invitation.go | 42 +++++++------- 4 files changed, 66 insertions(+), 64 deletions(-) diff --git a/mongodbatlas/data_source_mongodbatlas_org_invitation.go b/mongodbatlas/data_source_mongodbatlas_org_invitation.go index 18eb4b0559..658f45fda4 100644 --- a/mongodbatlas/data_source_mongodbatlas_org_invitation.go +++ b/mongodbatlas/data_source_mongodbatlas_org_invitation.go @@ -56,35 +56,35 @@ func dataSourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Reso orgInvitation, _, err := conn.Organizations.Invitation(ctx, orgID, invitationID) if err != nil { - return diag.FromErr(fmt.Errorf("error getting Organization Invitation information: %s", err)) + return diag.FromErr(fmt.Errorf("error getting Organization Invitation information: %w", err)) } if err := d.Set("username", orgInvitation.Username); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("org_id", orgInvitation.GroupID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("invitation_id", orgInvitation.ID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("expires_at", orgInvitation.ExpiresAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("created_at", orgInvitation.CreatedAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `created_at` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `created_at` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("inviter_username", orgInvitation.InviterUsername); err != nil { - return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("roles", orgInvitation.Roles); err != nil { - return diag.FromErr(fmt.Errorf("error getting `roles` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `roles` for Organization Invitation (%s): %w", d.Id(), err)) } d.SetId(encodeStateID(map[string]string{ diff --git a/mongodbatlas/data_source_mongodbatlas_project_invitation.go b/mongodbatlas/data_source_mongodbatlas_project_invitation.go index efe64b3b50..88b4dca08f 100644 --- a/mongodbatlas/data_source_mongodbatlas_project_invitation.go +++ b/mongodbatlas/data_source_mongodbatlas_project_invitation.go @@ -56,31 +56,31 @@ func dataSourceMongoDBAtlasProjectInvitationRead(ctx context.Context, d *schema. projectInvitation, _, err := conn.Projects.Invitation(ctx, projectID, invitationID) if err != nil { - return diag.FromErr(fmt.Errorf("error getting Project Invitation information: %s", err)) + return diag.FromErr(fmt.Errorf("error getting Project Invitation information: %w", err)) } if err := d.Set("username", projectInvitation.Username); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("project_id", projectInvitation.GroupID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("invitation_id", projectInvitation.ID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("expires_at", projectInvitation.ExpiresAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `expires_at` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("created_at", projectInvitation.CreatedAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `created_at` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `created_at` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("inviter_username", projectInvitation.InviterUsername); err != nil { - return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("roles", projectInvitation.Roles); err != nil { diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index 2fb8d1d057..ec3ef9ab19 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -63,11 +63,12 @@ func resourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Resour username := ids["username"] invitationID := ids["invitation_id"] - orgInvitation, resp, err := conn.Organizations.Invitation(context.Background(), orgID, invitationID) + orgInvitation, resp, err := conn.Organizations.Invitation(ctx, orgID, invitationID) if err != nil { // case 404 // deleted in the backend case - if resp != nil && resp.StatusCode == http.StatusNotFound { + var target *atlas.ErrorResponse + if errors.As(err, &target) && target.ErrorCode == "NOT_FOUND" { d.SetId("") return nil } @@ -76,27 +77,27 @@ func resourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Resour } if err := d.Set("username", orgInvitation.Username); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("org_id", orgInvitation.GroupID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("invitation_id", orgInvitation.ID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("expires_at", orgInvitation.ExpiresAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("created_at", orgInvitation.CreatedAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `created_at` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `created_at` for Organization Invitation (%s): %w", d.Id(), err)) } if err := d.Set("roles", orgInvitation.Roles); err != nil { - return diag.FromErr(fmt.Errorf("error getting `roles` for Organization Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `roles` for Organization Invitation (%s): %w", d.Id(), err)) } d.SetId(encodeStateID(map[string]string{ @@ -118,12 +119,12 @@ func resourceMongoDBAtlasOrgInvitationCreate(ctx context.Context, d *schema.Reso return diag.FromErr(err) } - InvitationReq := &matlas.Invitation{ + invitationReq := &matlas.Invitation{ Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), Username: d.Get("username").(string), } - InvitationRes, resp, err := conn.Organizations.InviteUser(ctx, orgID, InvitationReq) + invitationRes, resp, err := conn.Organizations.InviteUser(ctx, orgID, invitationReq) if err != nil { // case 404 // deleted in the backend case @@ -131,13 +132,13 @@ func resourceMongoDBAtlasOrgInvitationCreate(ctx context.Context, d *schema.Reso d.SetId("") return nil } - return diag.FromErr(fmt.Errorf("error creating Organization invitation: %s", err)) + return diag.FromErr(fmt.Errorf("error creating Organization invitation for user %s: %w", d.Get("username").(string), err)) } d.SetId(encodeStateID(map[string]string{ - "username": InvitationRes.Username, - "org_id": InvitationRes.OrgID, - "invitation_id": InvitationRes.ID, + "username": invitationRes.Username, + "org_id": invitationRes.OrgID, + "invitation_id": invitationRes.ID, })) return resourceMongoDBAtlasOrgInvitationRead(ctx, d, meta) @@ -152,7 +153,7 @@ func resourceMongoDBAtlasOrgInvitationDelete(ctx context.Context, d *schema.Reso _, err := conn.Organizations.DeleteInvitation(ctx, orgID, invitationID) if err != nil { - return diag.FromErr(fmt.Errorf("error creating Organization invitation: %s for %s", username, err)) + return diag.FromErr(fmt.Errorf("error deleting Organization invitation for user %s: %w", username, err)) } return nil @@ -165,13 +166,13 @@ func resourceMongoDBAtlasOrgInvitationUpdate(ctx context.Context, d *schema.Reso username := ids["username"] invitationID := ids["invitation_id"] - InvitationReq := &matlas.Invitation{ + invitationReq := &matlas.Invitation{ Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), } - _, _, err := conn.Organizations.UpdateInvitationByID(ctx, orgID, invitationID, InvitationReq) + _, _, err := conn.Organizations.UpdateInvitationByID(ctx, orgID, invitationID, invitationReq) if err != nil { - return diag.FromErr(fmt.Errorf("error creating Organization invitation: %s for %s", username, err)) + return diag.FromErr(fmt.Errorf("error updating Organization invitation for user %s: for %w", username, err)) } return resourceMongoDBAtlasOrgInvitationRead(ctx, d, meta) @@ -186,7 +187,7 @@ func resourceMongoDBAtlasOrgInvitationImportState(ctx context.Context, d *schema orgInvitations, _, err := conn.Organizations.Invitations(ctx, orgID, nil) if err != nil { - return nil, fmt.Errorf("couldn't import Organization invitations, error: %s", err) + return nil, fmt.Errorf("couldn't import Organization invitations, error: %w", err) } for _, orgInvitation := range orgInvitations { @@ -195,13 +196,13 @@ func resourceMongoDBAtlasOrgInvitationImportState(ctx context.Context, d *schema } if err := d.Set("username", orgInvitation.Username); err != nil { - return nil, fmt.Errorf("error getting `username` for Organization Invitation (%s): %s", username, err) + return nil, fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", username, err) } if err := d.Set("org_id", orgInvitation.GroupID); err != nil { - return nil, fmt.Errorf("error getting `org_id` for Organization Invitation (%s): %s", username, err) + return nil, fmt.Errorf("error getting `org_id` for Organization Invitation (%s): %w", username, err) } if err := d.Set("invitation_id", orgInvitation.ID); err != nil { - return nil, fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %s", username, err) + return nil, fmt.Errorf("error getting `invitation_id` for Organization Invitation (%s): %w", username, err) } d.SetId(encodeStateID(map[string]string{ "username": username, @@ -219,7 +220,7 @@ func splitOrgInvitationImportID(id string) (orgID, username string, err error) { parts := re.FindStringSubmatch(id) if len(parts) != 3 { - err = fmt.Errorf("import format error: to import a Organization Invitation, use the format {project_id}-{username}") + err = fmt.Errorf("import format error: to import a Organization Invitation, use the format {org_id}-{username}") return } @@ -230,11 +231,12 @@ func splitOrgInvitationImportID(id string) (orgID, username string, err error) { } func validateOrgRoles(list *schema.Set) error { - if rs := list.List(); list.Len() > 0 { - for _, role := range rs { - if !validateOrgRole(role.(string)) { - return fmt.Errorf("error creating an invite: %s is an invalid role for a Organization", role) - } + if list.Len() == 0 { + return nil + } + for _, role := range list.List() { + if !validateOrgRole(role.(string)) { + return fmt.Errorf("error creating an invite: %s is an invalid role for a Organization", role) } } diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation.go b/mongodbatlas/resource_mongodbatlas_project_invitation.go index 7e26dd94c4..38ba4492db 100644 --- a/mongodbatlas/resource_mongodbatlas_project_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_project_invitation.go @@ -63,7 +63,7 @@ func resourceMongoDBAtlasProjectInvitationRead(ctx context.Context, d *schema.Re username := ids["username"] invitationID := ids["invitation_id"] - projectInvitation, resp, err := conn.Projects.Invitation(context.Background(), projectID, invitationID) + projectInvitation, resp, err := conn.Projects.Invitation(ctx, projectID, invitationID) if err != nil { // case 404 // deleted in the backend case @@ -72,31 +72,31 @@ func resourceMongoDBAtlasProjectInvitationRead(ctx context.Context, d *schema.Re return nil } - return diag.FromErr(fmt.Errorf("error getting Project Invitation information: %s", err)) + return diag.FromErr(fmt.Errorf("error getting Project Invitation information: %w", err)) } if err := d.Set("username", projectInvitation.Username); err != nil { - return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `username` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("project_id", projectInvitation.GroupID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `project_id` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `project_id` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("invitation_id", projectInvitation.ID); err != nil { - return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("expires_at", projectInvitation.ExpiresAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `expires_at` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `expires_at` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("created_at", projectInvitation.CreatedAt); err != nil { - return diag.FromErr(fmt.Errorf("error getting `created_at` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `created_at` for Project Invitation (%s): %w", d.Id(), err)) } if err := d.Set("roles", projectInvitation.Roles); err != nil { - return diag.FromErr(fmt.Errorf("error getting `roles` for Project Invitation (%s): %s", d.Id(), err)) + return diag.FromErr(fmt.Errorf("error getting `roles` for Project Invitation (%s): %w", d.Id(), err)) } d.SetId(encodeStateID(map[string]string{ @@ -118,12 +118,12 @@ func resourceMongoDBAtlasProjectInvitationCreate(ctx context.Context, d *schema. return diag.FromErr(err) } - InvitationReq := &matlas.Invitation{ + invitationReq := &matlas.Invitation{ Roles: createProjectStringListFromSetSchema(d.Get("roles").(*schema.Set)), Username: d.Get("username").(string), } - InvitationRes, resp, err := conn.Projects.InviteUser(ctx, projectID, InvitationReq) + invitationRes, resp, err := conn.Projects.InviteUser(ctx, projectID, invitationReq) if err != nil { // case 404 // deleted in the backend case @@ -131,13 +131,13 @@ func resourceMongoDBAtlasProjectInvitationCreate(ctx context.Context, d *schema. d.SetId("") return nil } - return diag.FromErr(fmt.Errorf("error creating Atlas user: %s", err)) + return diag.FromErr(fmt.Errorf("error creating Project invitation for user %s: %w", d.Get("username").(string), err)) } d.SetId(encodeStateID(map[string]string{ - "username": InvitationRes.Username, - "project_id": InvitationRes.GroupID, - "invitation_id": InvitationRes.ID, + "username": invitationRes.Username, + "project_id": invitationRes.GroupID, + "invitation_id": invitationRes.ID, })) return resourceMongoDBAtlasProjectInvitationRead(ctx, d, meta) @@ -152,7 +152,7 @@ func resourceMongoDBAtlasProjectInvitationDelete(ctx context.Context, d *schema. _, err := conn.Projects.DeleteInvitation(ctx, projectID, invitationID) if err != nil { - return diag.FromErr(fmt.Errorf("error creating Project invitation: %s for %s", username, err)) + return diag.FromErr(fmt.Errorf("error deleting Project invitation for user %s: %w", username, err)) } return nil @@ -165,13 +165,13 @@ func resourceMongoDBAtlasProjectInvitationUpdate(ctx context.Context, d *schema. username := ids["username"] invitationID := ids["invitation_id"] - InvitationReq := &matlas.Invitation{ + invitationReq := &matlas.Invitation{ Roles: createProjectStringListFromSetSchema(d.Get("roles").(*schema.Set)), } - _, _, err := conn.Projects.UpdateInvitationByID(ctx, projectID, invitationID, InvitationReq) + _, _, err := conn.Projects.UpdateInvitationByID(ctx, projectID, invitationID, invitationReq) if err != nil { - return diag.FromErr(fmt.Errorf("error creating Project invitation: %s for %s", username, err)) + return diag.FromErr(fmt.Errorf("error updating Project invitation for user %s: %w", username, err)) } return resourceMongoDBAtlasProjectInvitationRead(ctx, d, meta) @@ -195,13 +195,13 @@ func resourceMongoDBAtlasProjectInvitationImportState(ctx context.Context, d *sc } if err := d.Set("username", projectInvitation.Username); err != nil { - return nil, fmt.Errorf("error getting `username` for Project Invitation (%s): %s", username, err) + return nil, fmt.Errorf("error getting `username` for Project Invitation (%s): %w", username, err) } if err := d.Set("project_id", projectInvitation.GroupID); err != nil { - return nil, fmt.Errorf("error getting `project_id` for Project Invitation (%s): %s", username, err) + return nil, fmt.Errorf("error getting `project_id` for Project Invitation (%s): %w", username, err) } if err := d.Set("invitation_id", projectInvitation.ID); err != nil { - return nil, fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %s", username, err) + return nil, fmt.Errorf("error getting `invitation_id` for Project Invitation (%s): %w", username, err) } d.SetId(encodeStateID(map[string]string{ "username": username, From 9e1d62effc5c6be52d4e4d7d8f268caa8c99b3ea Mon Sep 17 00:00:00 2001 From: beergeek Date: Tue, 14 Sep 2021 21:59:02 +1000 Subject: [PATCH 05/16] Fix the linting issues --- mongodbatlas/resource_mongodbatlas_org_invitation.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index ec3ef9ab19..2d786a1e57 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -2,6 +2,7 @@ package mongodbatlas import ( "context" + "errors" "fmt" "net/http" "regexp" @@ -63,11 +64,11 @@ func resourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Resour username := ids["username"] invitationID := ids["invitation_id"] - orgInvitation, resp, err := conn.Organizations.Invitation(ctx, orgID, invitationID) + orgInvitation, _, err := conn.Organizations.Invitation(ctx, orgID, invitationID) if err != nil { // case 404 // deleted in the backend case - var target *atlas.ErrorResponse + var target *matlas.ErrorResponse if errors.As(err, &target) && target.ErrorCode == "NOT_FOUND" { d.SetId("") return nil From 1da804c1364142ffc2f36f01dc9c2e7040cc8850 Mon Sep 17 00:00:00 2001 From: beergeek Date: Wed, 15 Sep 2021 13:56:17 +1000 Subject: [PATCH 06/16] Fix the linting issues --- mongodbatlas/resource_mongodbatlas_org_invitation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index 2d786a1e57..649d9b222b 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -74,7 +74,7 @@ func resourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Resour return nil } - return diag.FromErr(fmt.Errorf("error getting Organization Invitation information: %s", err)) + return diag.FromErr(fmt.Errorf("error getting Organization Invitation information: %w", err)) } if err := d.Set("username", orgInvitation.Username); err != nil { From 90bcad74b2cc971e3ec61804f257c562343ea669 Mon Sep 17 00:00:00 2001 From: beergeek Date: Wed, 22 Sep 2021 10:12:09 +1000 Subject: [PATCH 07/16] Add tests --- ...source_mongodbatlas_org_invitation_test.go | 54 +++++ ...ce_mongodbatlas_project_invitation_test.go | 54 +++++ ...source_mongodbatlas_org_invitation_test.go | 198 +++++++++++++++++ ...ce_mongodbatlas_project_invitation_test.go | 204 ++++++++++++++++++ 4 files changed, 510 insertions(+) create mode 100644 mongodbatlas/data_source_mongodbatlas_org_invitation_test.go create mode 100644 mongodbatlas/data_source_mongodbatlas_project_invitation_test.go create mode 100644 mongodbatlas/resource_mongodbatlas_org_invitation_test.go create mode 100644 mongodbatlas/resource_mongodbatlas_project_invitation_test.go diff --git a/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go b/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go new file mode 100644 index 0000000000..34a93a7754 --- /dev/null +++ b/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go @@ -0,0 +1,54 @@ +package mongodbatlas + +import ( + "fmt" + "os" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccDataSourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { + var ( + dataSourceName = "mongodbatlas_org_invitations.test" + orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") + name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) + initialRole = []string{"ORG_OWNER"} + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckMongoDBAtlasOrgInvitationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceMongoDBAtlasOrgInvitationConfig(orgID, name, initialRole), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "org_id"), + resource.TestCheckResourceAttrSet(dataSourceName, "username"), + resource.TestCheckResourceAttrSet(dataSourceName, "invitation_id"), + resource.TestCheckResourceAttr(dataSourceName, "username", name), + resource.TestCheckResourceAttr(dataSourceName, "roles.#", "1"), + ), + }, + }, + }) +} + +func testAccDataSourceMongoDBAtlasOrgInvitationConfig(orgID, username string, roles []string) string { + return fmt.Sprintf(` + resource "mongodbatlas_org_invitation" "test" { + org_id = "%s" + username = "%s" + roles = %s + } + + data "mongodbatlas_org_invitation" "test" { + org_id = mongodbatlas_org_invitation.test.org_id + username = mongodbatlas_org_invitation.test.username + }`, orgID, username, + strings.ReplaceAll(fmt.Sprintf("%+q", roles), " ", ","), + ) +} diff --git a/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go b/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go new file mode 100644 index 0000000000..00f4106579 --- /dev/null +++ b/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go @@ -0,0 +1,54 @@ +package mongodbatlas + +import ( + "fmt" + "os" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccDataSourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { + var ( + dataSourceName = "mongodbatlas_project_invitations.test" + projectID = os.Getenv("MONGODB_ATLAS_PROJECT_ID") + name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) + initialRole = []string{"GROUP_OWNER"} + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckMongoDBAtlasProjectInvitationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceMongoDBAtlasProjectInvitationConfig(projectID, name, initialRole), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(dataSourceName, "project_id"), + resource.TestCheckResourceAttrSet(dataSourceName, "username"), + resource.TestCheckResourceAttrSet(dataSourceName, "invitation_id"), + resource.TestCheckResourceAttr(dataSourceName, "username", name), + resource.TestCheckResourceAttr(dataSourceName, "roles.#", "1"), + ), + }, + }, + }) +} + +func testAccDataSourceMongoDBAtlasProjectInvitationConfig(projectID, username string, roles []string) string { + return fmt.Sprintf(` + resource "mongodbatlas_project_invitation" "test" { + project_id = "%s" + username = "%s" + roles = %s + } + + data "mongodbatlas_project_invitation" "test" { + project_id = mongodbatlas_project_invitation.test.projectID + username = mongodbatlas_project_invitation.test.username + }`, projectID, username, + strings.ReplaceAll(fmt.Sprintf("%+q", roles), " ", ","), + ) +} diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation_test.go b/mongodbatlas/resource_mongodbatlas_org_invitation_test.go new file mode 100644 index 0000000000..37880cfb2c --- /dev/null +++ b/mongodbatlas/resource_mongodbatlas_org_invitation_test.go @@ -0,0 +1,198 @@ +package mongodbatlas + +import ( + "context" + "fmt" + "log" + "os" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + matlas "go.mongodb.org/atlas/mongodbatlas" +) + +func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { + var ( + invitation matlas.Invitation + resourceName = "mongodbatlas_org_invitations.test" + orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") + name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) + initialRole = []string{"ORG_OWNER"} + updateRoles = []string{"ORG_GROUP_CREATOR", "ORG_BILLING_ADMIN"} + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckMongoDBAtlasOrgInvitationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, initialRole), + Check: resource.ComposeTestCheckFunc( + testAccCheckMongoDBAtlasOrgInvitationExists(resourceName, &invitation), + testAccCheckMongoDBAtlasOrgInvitationUsernameAttribute(&invitation, name), + testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(&invitation, initialRole), + resource.TestCheckResourceAttrSet(resourceName, "org_id"), + resource.TestCheckResourceAttrSet(resourceName, "username"), + resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), + resource.TestCheckResourceAttr(resourceName, "username", name), + resource.TestCheckResourceAttr(resourceName, "roles.#", "1"), + ), + }, + { + Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, updateRoles), + Check: resource.ComposeTestCheckFunc( + testAccCheckMongoDBAtlasOrgInvitationExists(resourceName, &invitation), + testAccCheckMongoDBAtlasOrgInvitationUsernameAttribute(&invitation, name), + testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(&invitation, updateRoles), + resource.TestCheckResourceAttrSet(resourceName, "username"), + resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), + resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "roles.#", "2"), + ), + }, + }, + }) +} + +func TestAccResourceMongoDBAtlasOrgInvitation_importBasic(t *testing.T) { + var ( + resourceName = "mongodbatlas_invitations.test" + orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") + name = fmt.Sprintf("test-acc-%s", acctest.RandString(10)) + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckMongoDBAtlasOrgInvitationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, []string{"mongodbatlas.testing@gmail.com"}), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "org_id"), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "usernames.#"), + resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), + + resource.TestCheckResourceAttr(resourceName, "org_id", orgID), + resource.TestCheckResourceAttr(resourceName, "name", name), + resource.TestCheckResourceAttr(resourceName, "usernames.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccCheckMongoDBAtlasOrgInvitationStateIDFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckMongoDBAtlasOrgInvitationExists(resourceName string, invitation *matlas.Invitation) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*MongoDBClient).Atlas + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + + ids := decodeStateID(rs.Primary.ID) + + orgID := ids["org_id"] + username := ids["username"] + invitationID := ids["invitation_id"] + + if orgID == "" && username == "" && invitationID == "" { + return fmt.Errorf("no ID is set") + } + + log.Printf("[DEBUG] orgID: %s", orgID) + log.Printf("[DEBUG] username: %s", username) + log.Printf("[DEBUG] invitationID: %s", invitationID) + + invitationResp, _, err := conn.Organizations.Invitation(context.Background(), orgID, invitationID) + if err == nil { + *invitation = *invitationResp + return nil + } + + return fmt.Errorf("invitation(%s) does not exist", invitationID) + } +} + +func testAccCheckMongoDBAtlasOrgInvitationUsernameAttribute(invitation *matlas.Invitation, username string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if invitation.Username != username { + return fmt.Errorf("bad name: %s", invitation.Username) + } + + return nil + } +} + +func testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(invitation *matlas.Invitation, roles []string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if len(roles) > 0 { + for _, role := range roles { + for _, currentRole := range invitation.Roles { + if currentRole == role { + return nil + } + } + } + } + + return fmt.Errorf("bad role: %s", invitation.Roles) + } +} + +func testAccCheckMongoDBAtlasOrgInvitationDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*MongoDBClient).Atlas + + for _, rs := range s.RootModule().Resources { + if rs.Type != "mongodbatlas_invitations" { + continue + } + + ids := decodeStateID(rs.Primary.ID) + + orgID := ids["org_id"] + invitationID := ids["invitation_id"] + + // Try to find the invitation + _, _, err := conn.Organizations.Invitation(context.Background(), orgID, invitationID) + if err == nil { + return fmt.Errorf("invitation (%s) still exists", invitationID) + } + } + + return nil +} + +func testAccCheckMongoDBAtlasOrgInvitationStateIDFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("not found: %s", resourceName) + } + + return fmt.Sprintf("%s-%s", rs.Primary.Attributes["org_id"], rs.Primary.Attributes["invitation_id"]), nil + } +} + +func testAccMongoDBAtlasOrgInvitationConfig(orgID, username string, roles []string) string { + return fmt.Sprintf(` + resource "mongodbatlas_invitations" "test" { + org_id = "%s" + username = "%s" + roles = %s + }`, orgID, username, + strings.ReplaceAll(fmt.Sprintf("%+q", roles), " ", ","), + ) +} diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation_test.go b/mongodbatlas/resource_mongodbatlas_project_invitation_test.go new file mode 100644 index 0000000000..c912c5f804 --- /dev/null +++ b/mongodbatlas/resource_mongodbatlas_project_invitation_test.go @@ -0,0 +1,204 @@ +package mongodbatlas + +import ( + "context" + "fmt" + "log" + "os" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + matlas "go.mongodb.org/atlas/mongodbatlas" +) + +func TestAccResourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { + var ( + invitation matlas.Invitation + resourceName = "mongodbatlas_project_invitations.test" + projectID = os.Getenv("MONGODB_ATLAS_PROJECT_ID") + name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) + initialRole = []string{"GROUP_OWNER"} + updateRoles = []string{"GROUP_DATA_ACCESS_ADMIN", "GROUP_CLUSTER_MANAGER"} + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckMongoDBAtlasProjectInvitationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMongoDBAtlasProjectInvitationConfig(projectID, name, initialRole), + Check: resource.ComposeTestCheckFunc( + testAccCheckMongoDBAtlasProjectInvitationExists(resourceName, &invitation), + testAccCheckMongoDBAtlasProjectInvitationUsernameAttribute(&invitation, name), + testAccCheckMongoDBAtlasProjectInvitationRoleAttribute(&invitation, initialRole), + resource.TestCheckResourceAttrSet(resourceName, "project_id"), + resource.TestCheckResourceAttrSet(resourceName, "username"), + resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), + resource.TestCheckResourceAttrSet(resourceName, "roles.#"), + resource.TestCheckResourceAttr(resourceName, "project_id", projectID), + resource.TestCheckResourceAttr(resourceName, "username", name), + resource.TestCheckResourceAttr(resourceName, "roles.#", "1"), + ), + }, + { + Config: testAccMongoDBAtlasProjectInvitationConfig(projectID, name, updateRoles), + Check: resource.ComposeTestCheckFunc( + testAccCheckMongoDBAtlasProjectInvitationExists(resourceName, &invitation), + testAccCheckMongoDBAtlasProjectInvitationUsernameAttribute(&invitation, name), + testAccCheckMongoDBAtlasProjectInvitationRoleAttribute(&invitation, updateRoles), + resource.TestCheckResourceAttrSet(resourceName, "project_id"), + resource.TestCheckResourceAttrSet(resourceName, "username"), + resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), + resource.TestCheckResourceAttrSet(resourceName, "roles.#"), + resource.TestCheckResourceAttr(resourceName, "project_id", projectID), + resource.TestCheckResourceAttr(resourceName, "username", name), + resource.TestCheckResourceAttr(resourceName, "roles.#", "2"), + ), + }, + }, + }) +} + +func TestAccResourceMongoDBAtlasProjectInvitation_importBasic(t *testing.T) { + var ( + resourceName = "mongodbatlas_project_invitations.test" + projectID = os.Getenv("MONGODB_ATLAS_PROJECT_ID") + name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) + initialRole = []string{"GROUP_OWNER"} + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: testAccProviderFactories, + CheckDestroy: testAccCheckMongoDBAtlasProjectInvitationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccMongoDBAtlasProjectInvitationConfig(projectID, name, initialRole), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "project_id"), + resource.TestCheckResourceAttrSet(resourceName, "username"), + resource.TestCheckResourceAttrSet(resourceName, "roles.#"), + resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), + + resource.TestCheckResourceAttr(resourceName, "project_id", projectID), + resource.TestCheckResourceAttr(resourceName, "username", name), + resource.TestCheckResourceAttr(resourceName, "roles.#", "1"), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: testAccCheckMongoDBAtlasProjectInvitationStateIDFunc(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckMongoDBAtlasProjectInvitationExists(resourceName string, invitation *matlas.Invitation) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*MongoDBClient).Atlas + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("not found: %s", resourceName) + } + + ids := decodeStateID(rs.Primary.ID) + + projectID := ids["project_id"] + username := ids["username"] + invitationID := ids["invitation_id"] + + if projectID == "" && username == "" && invitationID == "" { + return fmt.Errorf("no ID is set") + } + + log.Printf("[DEBUG] projectID: %s", projectID) + log.Printf("[DEBUG] username: %s", username) + log.Printf("[DEBUG] invitationID: %s", invitationID) + + invitationResp, _, err := conn.Projects.Invitation(context.Background(), projectID, invitationID) + if err == nil { + *invitation = *invitationResp + return nil + } + + return fmt.Errorf("invitation(%s) does not exist", invitationID) + } +} + +func testAccCheckMongoDBAtlasProjectInvitationUsernameAttribute(invitation *matlas.Invitation, username string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if invitation.Username != username { + return fmt.Errorf("bad name: %s", invitation.Username) + } + + return nil + } +} + +func testAccCheckMongoDBAtlasProjectInvitationRoleAttribute(invitation *matlas.Invitation, roles []string) resource.TestCheckFunc { + return func(s *terraform.State) error { + if len(roles) > 0 { + for _, role := range roles { + for _, currentRole := range invitation.Roles { + if currentRole == role { + return nil + } + } + } + } + + return fmt.Errorf("bad role: %s", invitation.Roles) + } +} + +func testAccCheckMongoDBAtlasProjectInvitationDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*MongoDBClient).Atlas + + for _, rs := range s.RootModule().Resources { + if rs.Type != "mongodbatlas_invitations" { + continue + } + + ids := decodeStateID(rs.Primary.ID) + + projectID := ids["project_id"] + invitationID := ids["invitation_id"] + + // Try to find the invitation + _, _, err := conn.Projects.Invitation(context.Background(), projectID, invitationID) + if err == nil { + return fmt.Errorf("invitation (%s) still exists", invitationID) + } + } + + return nil +} + +func testAccCheckMongoDBAtlasProjectInvitationStateIDFunc(resourceName string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("not found: %s", resourceName) + } + + return fmt.Sprintf("%s-%s", rs.Primary.Attributes["org_id"], rs.Primary.Attributes["invitation_id"]), nil + } +} + +func testAccMongoDBAtlasProjectInvitationConfig(projectID, username string, roles []string) string { + return fmt.Sprintf(` + resource "mongodbatlas_invitations" "test" { + project_id = "%s" + username = "%s" + roles = %s + }`, projectID, username, + strings.ReplaceAll(fmt.Sprintf("%+q", roles), " ", ","), + ) +} From a3c479ad0e0f2db1776b5272feedc7013e1d9b0c Mon Sep 17 00:00:00 2001 From: beergeek Date: Fri, 24 Sep 2021 09:16:03 +1000 Subject: [PATCH 08/16] Refactor portions of the code to reduce the amount of code required --- .../resource_mongodbatlas_org_invitation.go | 44 ++++-------------- ...esource_mongodbatlas_project_invitation.go | 45 ++++--------------- 2 files changed, 17 insertions(+), 72 deletions(-) diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index 649d9b222b..cfd28d8435 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -8,6 +8,7 @@ import ( "regexp" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" matlas "go.mongodb.org/atlas/mongodbatlas" @@ -50,6 +51,13 @@ func resourceMongoDBAtlasOrgInvitation() *schema.Resource { Required: true, Elem: &schema.Schema{ Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + "ORG_OWNER", + "ORG_GROUP_CREATOR", + "ORG_BILLING_ADMIN", + "ORG_READ_ONLY", + "ORG_MEMBER", + }, false), }, }, }, @@ -115,11 +123,6 @@ func resourceMongoDBAtlasOrgInvitationCreate(ctx context.Context, d *schema.Reso conn := meta.(*MongoDBClient).Atlas orgID := d.Get("org_id").(string) - err := validateOrgRoles(d.Get("roles").(*schema.Set)) - if err != nil { - return diag.FromErr(err) - } - invitationReq := &matlas.Invitation{ Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), Username: d.Get("username").(string), @@ -231,37 +234,6 @@ func splitOrgInvitationImportID(id string) (orgID, username string, err error) { return } -func validateOrgRoles(list *schema.Set) error { - if list.Len() == 0 { - return nil - } - for _, role := range list.List() { - if !validateOrgRole(role.(string)) { - return fmt.Errorf("error creating an invite: %s is an invalid role for a Organization", role) - } - } - - return nil -} - -func validateOrgRole(str string) bool { - orgRoles := []string{ - "ORG_OWNER", - "ORG_GROUP_CREATOR", - "ORG_BILLING_ADMIN", - "ORG_READ_ONLY", - "ORG_MEMBER", - } - - for _, validRole := range orgRoles { - if validRole == str { - return true - } - } - - return false -} - func createOrgStringListFromSetSchema(list *schema.Set) []string { res := make([]string, list.Len()) for i, v := range list.List() { diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation.go b/mongodbatlas/resource_mongodbatlas_project_invitation.go index 38ba4492db..ad32482dc8 100644 --- a/mongodbatlas/resource_mongodbatlas_project_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_project_invitation.go @@ -7,6 +7,7 @@ import ( "regexp" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" matlas "go.mongodb.org/atlas/mongodbatlas" @@ -49,6 +50,14 @@ func resourceMongoDBAtlasProjectInvitation() *schema.Resource { Required: true, Elem: &schema.Schema{ Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + "GROUP_OWNER", + "GROUP_CLUSTER_MANAGER", + "GROUP_READ_ONLY", + "GROUP_DATA_ACCESS_ADMIN", + "GROUP_DATA_ACCESS_READ_WRITE", + "GROUP_DATA_ACCESS_READ_ONLY", + }, false), }, }, }, @@ -113,11 +122,6 @@ func resourceMongoDBAtlasProjectInvitationCreate(ctx context.Context, d *schema. conn := meta.(*MongoDBClient).Atlas projectID := d.Get("project_id").(string) - err := validateProjectRoles(d.Get("roles").(*schema.Set)) - if err != nil { - return diag.FromErr(err) - } - invitationReq := &matlas.Invitation{ Roles: createProjectStringListFromSetSchema(d.Get("roles").(*schema.Set)), Username: d.Get("username").(string), @@ -229,37 +233,6 @@ func splitProjectInvitationImportID(id string) (projectID, username string, err return } -func validateProjectRoles(list *schema.Set) error { - if rs := list.List(); list.Len() > 0 { - for _, role := range rs { - if !validateProjectRole(role.(string)) { - return fmt.Errorf("error creating an invite: %s is an invalid role for a Project", role) - } - } - } - - return nil -} - -func validateProjectRole(str string) bool { - projRoles := []string{ - "GROUP_OWNER", - "GROUP_CLUSTER_MANAGER", - "GROUP_READ_ONLY", - "GROUP_DATA_ACCESS_ADMIN", - "GROUP_DATA_ACCESS_READ_WRITE", - "GROUP_DATA_ACCESS_READ_ONLY", - } - - for _, validRole := range projRoles { - if validRole == str { - return true - } - } - - return false -} - func createProjectStringListFromSetSchema(list *schema.Set) []string { res := make([]string, list.Len()) for i, v := range list.List() { From 53f4c46dfc8252662309df0eba20ae04d809caaf Mon Sep 17 00:00:00 2001 From: beergeek Date: Fri, 24 Sep 2021 19:39:37 +1000 Subject: [PATCH 09/16] Changes as requested --- ...source_mongodbatlas_org_invitation_test.go | 2 +- ...ce_mongodbatlas_project_invitation_test.go | 2 +- .../resource_mongodbatlas_org_invitation.go | 13 ++--------- ...source_mongodbatlas_org_invitation_test.go | 22 +++++++++---------- ...esource_mongodbatlas_project_invitation.go | 2 +- ...ce_mongodbatlas_project_invitation_test.go | 12 +++++----- 6 files changed, 21 insertions(+), 32 deletions(-) diff --git a/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go b/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go index 34a93a7754..3cb84405ab 100644 --- a/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go +++ b/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go @@ -49,6 +49,6 @@ func testAccDataSourceMongoDBAtlasOrgInvitationConfig(orgID, username string, ro org_id = mongodbatlas_org_invitation.test.org_id username = mongodbatlas_org_invitation.test.username }`, orgID, username, - strings.ReplaceAll(fmt.Sprintf("%+q", roles), " ", ","), + strings.Join(roles, ","), ) } diff --git a/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go b/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go index 00f4106579..9da850c1af 100644 --- a/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go +++ b/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go @@ -49,6 +49,6 @@ func testAccDataSourceMongoDBAtlasProjectInvitationConfig(projectID, username st project_id = mongodbatlas_project_invitation.test.projectID username = mongodbatlas_project_invitation.test.username }`, projectID, username, - strings.ReplaceAll(fmt.Sprintf("%+q", roles), " ", ","), + strings.Join(roles, ","), ) } diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index cfd28d8435..f3bb43cafd 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -124,7 +124,7 @@ func resourceMongoDBAtlasOrgInvitationCreate(ctx context.Context, d *schema.Reso orgID := d.Get("org_id").(string) invitationReq := &matlas.Invitation{ - Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), + Roles: expandStringListFromSetSchema(d.Get("roles").(*schema.Set)), Username: d.Get("username").(string), } @@ -171,7 +171,7 @@ func resourceMongoDBAtlasOrgInvitationUpdate(ctx context.Context, d *schema.Reso invitationID := ids["invitation_id"] invitationReq := &matlas.Invitation{ - Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), + Roles: expandStringListFromSetSchema(d.Get("roles").(*schema.Set)), } _, _, err := conn.Organizations.UpdateInvitationByID(ctx, orgID, invitationID, invitationReq) @@ -233,12 +233,3 @@ func splitOrgInvitationImportID(id string) (orgID, username string, err error) { return } - -func createOrgStringListFromSetSchema(list *schema.Set) []string { - res := make([]string, list.Len()) - for i, v := range list.List() { - res[i] = v.(string) - } - - return res -} diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation_test.go b/mongodbatlas/resource_mongodbatlas_org_invitation_test.go index 37880cfb2c..bc026d7664 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation_test.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation_test.go @@ -32,7 +32,7 @@ func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { { Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, initialRole), Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasOrgInvitationExists(resourceName, &invitation), + testAccCheckMongoDBAtlasOrgInvitationExists(resourceName, &invitation, t), testAccCheckMongoDBAtlasOrgInvitationUsernameAttribute(&invitation, name), testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(&invitation, initialRole), resource.TestCheckResourceAttrSet(resourceName, "org_id"), @@ -45,7 +45,7 @@ func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { { Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, updateRoles), Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasOrgInvitationExists(resourceName, &invitation), + testAccCheckMongoDBAtlasOrgInvitationExists(resourceName, &invitation, t), testAccCheckMongoDBAtlasOrgInvitationUsernameAttribute(&invitation, name), testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(&invitation, updateRoles), resource.TestCheckResourceAttrSet(resourceName, "username"), @@ -93,7 +93,7 @@ func TestAccResourceMongoDBAtlasOrgInvitation_importBasic(t *testing.T) { }) } -func testAccCheckMongoDBAtlasOrgInvitationExists(resourceName string, invitation *matlas.Invitation) resource.TestCheckFunc { +func testAccCheckMongoDBAtlasOrgInvitationExists(resourceName string, invitation *matlas.Invitation, t *testing.T) resource.TestCheckFunc { return func(s *terraform.State) error { conn := testAccProvider.Meta().(*MongoDBClient).Atlas @@ -112,9 +112,9 @@ func testAccCheckMongoDBAtlasOrgInvitationExists(resourceName string, invitation return fmt.Errorf("no ID is set") } - log.Printf("[DEBUG] orgID: %s", orgID) - log.Printf("[DEBUG] username: %s", username) - log.Printf("[DEBUG] invitationID: %s", invitationID) + t.Logf("orgID: %s", orgID) + t.Logf("username: %s", username) + t.Logf("invitationID: %s", invitationID) invitationResp, _, err := conn.Organizations.Invitation(context.Background(), orgID, invitationID) if err == nil { @@ -138,12 +138,10 @@ func testAccCheckMongoDBAtlasOrgInvitationUsernameAttribute(invitation *matlas.I func testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(invitation *matlas.Invitation, roles []string) resource.TestCheckFunc { return func(s *terraform.State) error { - if len(roles) > 0 { - for _, role := range roles { - for _, currentRole := range invitation.Roles { - if currentRole == role { - return nil - } + for _, role := range roles { + for _, currentRole := range invitation.Roles { + if currentRole == role { + return nil } } } diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation.go b/mongodbatlas/resource_mongodbatlas_project_invitation.go index ad32482dc8..7c399faa0e 100644 --- a/mongodbatlas/resource_mongodbatlas_project_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_project_invitation.go @@ -170,7 +170,7 @@ func resourceMongoDBAtlasProjectInvitationUpdate(ctx context.Context, d *schema. invitationID := ids["invitation_id"] invitationReq := &matlas.Invitation{ - Roles: createProjectStringListFromSetSchema(d.Get("roles").(*schema.Set)), + Roles: expandStringListFromSetSchema(d.Get("roles").(*schema.Set)), } _, _, err := conn.Projects.UpdateInvitationByID(ctx, projectID, invitationID, invitationReq) diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation_test.go b/mongodbatlas/resource_mongodbatlas_project_invitation_test.go index c912c5f804..c35de37138 100644 --- a/mongodbatlas/resource_mongodbatlas_project_invitation_test.go +++ b/mongodbatlas/resource_mongodbatlas_project_invitation_test.go @@ -32,7 +32,7 @@ func TestAccResourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { { Config: testAccMongoDBAtlasProjectInvitationConfig(projectID, name, initialRole), Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasProjectInvitationExists(resourceName, &invitation), + testAccCheckMongoDBAtlasProjectInvitationExists(resourceName, &invitation, t), testAccCheckMongoDBAtlasProjectInvitationUsernameAttribute(&invitation, name), testAccCheckMongoDBAtlasProjectInvitationRoleAttribute(&invitation, initialRole), resource.TestCheckResourceAttrSet(resourceName, "project_id"), @@ -47,7 +47,7 @@ func TestAccResourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { { Config: testAccMongoDBAtlasProjectInvitationConfig(projectID, name, updateRoles), Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasProjectInvitationExists(resourceName, &invitation), + testAccCheckMongoDBAtlasProjectInvitationExists(resourceName, &invitation, t), testAccCheckMongoDBAtlasProjectInvitationUsernameAttribute(&invitation, name), testAccCheckMongoDBAtlasProjectInvitationRoleAttribute(&invitation, updateRoles), resource.TestCheckResourceAttrSet(resourceName, "project_id"), @@ -99,7 +99,7 @@ func TestAccResourceMongoDBAtlasProjectInvitation_importBasic(t *testing.T) { }) } -func testAccCheckMongoDBAtlasProjectInvitationExists(resourceName string, invitation *matlas.Invitation) resource.TestCheckFunc { +func testAccCheckMongoDBAtlasProjectInvitationExists(resourceName string, invitation *matlas.Invitation, t *testing.T) resource.TestCheckFunc { return func(s *terraform.State) error { conn := testAccProvider.Meta().(*MongoDBClient).Atlas @@ -118,9 +118,9 @@ func testAccCheckMongoDBAtlasProjectInvitationExists(resourceName string, invita return fmt.Errorf("no ID is set") } - log.Printf("[DEBUG] projectID: %s", projectID) - log.Printf("[DEBUG] username: %s", username) - log.Printf("[DEBUG] invitationID: %s", invitationID) + t.Logf("projectID: %s", projectID) + t.Logf("username: %s", username) + t.Logf("invitationID: %s", invitationID) invitationResp, _, err := conn.Projects.Invitation(context.Background(), projectID, invitationID) if err == nil { From 67305f47311935a7b7919583b9c4714f250d6b50 Mon Sep 17 00:00:00 2001 From: beergeek Date: Sat, 25 Sep 2021 08:52:44 +1000 Subject: [PATCH 10/16] Changes as requested --- .../resource_mongodbatlas_org_invitation_test.go | 9 ++++----- .../resource_mongodbatlas_project_invitation_test.go | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation_test.go b/mongodbatlas/resource_mongodbatlas_org_invitation_test.go index bc026d7664..b95a8c83dd 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation_test.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation_test.go @@ -3,7 +3,6 @@ package mongodbatlas import ( "context" "fmt" - "log" "os" "strings" "testing" @@ -32,7 +31,7 @@ func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { { Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, initialRole), Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasOrgInvitationExists(resourceName, &invitation, t), + testAccCheckMongoDBAtlasOrgInvitationExists(t, resourceName, &invitation), testAccCheckMongoDBAtlasOrgInvitationUsernameAttribute(&invitation, name), testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(&invitation, initialRole), resource.TestCheckResourceAttrSet(resourceName, "org_id"), @@ -45,7 +44,7 @@ func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { { Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, updateRoles), Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasOrgInvitationExists(resourceName, &invitation, t), + testAccCheckMongoDBAtlasOrgInvitationExists(t, resourceName, &invitation), testAccCheckMongoDBAtlasOrgInvitationUsernameAttribute(&invitation, name), testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(&invitation, updateRoles), resource.TestCheckResourceAttrSet(resourceName, "username"), @@ -93,7 +92,7 @@ func TestAccResourceMongoDBAtlasOrgInvitation_importBasic(t *testing.T) { }) } -func testAccCheckMongoDBAtlasOrgInvitationExists(resourceName string, invitation *matlas.Invitation, t *testing.T) resource.TestCheckFunc { +func testAccCheckMongoDBAtlasOrgInvitationExists(t *testing.T, resourceName string, invitation *matlas.Invitation) resource.TestCheckFunc { return func(s *terraform.State) error { conn := testAccProvider.Meta().(*MongoDBClient).Atlas @@ -191,6 +190,6 @@ func testAccMongoDBAtlasOrgInvitationConfig(orgID, username string, roles []stri username = "%s" roles = %s }`, orgID, username, - strings.ReplaceAll(fmt.Sprintf("%+q", roles), " ", ","), + strings.Join(roles, ","), ) } diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation_test.go b/mongodbatlas/resource_mongodbatlas_project_invitation_test.go index c35de37138..95667207dc 100644 --- a/mongodbatlas/resource_mongodbatlas_project_invitation_test.go +++ b/mongodbatlas/resource_mongodbatlas_project_invitation_test.go @@ -3,7 +3,6 @@ package mongodbatlas import ( "context" "fmt" - "log" "os" "strings" "testing" @@ -32,7 +31,7 @@ func TestAccResourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { { Config: testAccMongoDBAtlasProjectInvitationConfig(projectID, name, initialRole), Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasProjectInvitationExists(resourceName, &invitation, t), + testAccCheckMongoDBAtlasProjectInvitationExists(t, resourceName, &invitation), testAccCheckMongoDBAtlasProjectInvitationUsernameAttribute(&invitation, name), testAccCheckMongoDBAtlasProjectInvitationRoleAttribute(&invitation, initialRole), resource.TestCheckResourceAttrSet(resourceName, "project_id"), @@ -47,7 +46,7 @@ func TestAccResourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { { Config: testAccMongoDBAtlasProjectInvitationConfig(projectID, name, updateRoles), Check: resource.ComposeTestCheckFunc( - testAccCheckMongoDBAtlasProjectInvitationExists(resourceName, &invitation, t), + testAccCheckMongoDBAtlasProjectInvitationExists(t, resourceName, &invitation), testAccCheckMongoDBAtlasProjectInvitationUsernameAttribute(&invitation, name), testAccCheckMongoDBAtlasProjectInvitationRoleAttribute(&invitation, updateRoles), resource.TestCheckResourceAttrSet(resourceName, "project_id"), @@ -99,7 +98,7 @@ func TestAccResourceMongoDBAtlasProjectInvitation_importBasic(t *testing.T) { }) } -func testAccCheckMongoDBAtlasProjectInvitationExists(resourceName string, invitation *matlas.Invitation, t *testing.T) resource.TestCheckFunc { +func testAccCheckMongoDBAtlasProjectInvitationExists(t *testing.T, resourceName string, invitation *matlas.Invitation) resource.TestCheckFunc { return func(s *terraform.State) error { conn := testAccProvider.Meta().(*MongoDBClient).Atlas @@ -199,6 +198,6 @@ func testAccMongoDBAtlasProjectInvitationConfig(projectID, username string, role username = "%s" roles = %s }`, projectID, username, - strings.ReplaceAll(fmt.Sprintf("%+q", roles), " ", ","), + strings.Join(roles, ","), ) } From 259842482faffe1999143bd07a609068bd684c20 Mon Sep 17 00:00:00 2001 From: beergeek Date: Mon, 4 Oct 2021 10:48:08 +1100 Subject: [PATCH 11/16] Changes to code as requested, plus doc updates --- ...data_source_mongodbatlas_org_invitation.go | 13 ++++- ..._source_mongodbatlas_project_invitation.go | 2 +- .../resource_mongodbatlas_org_invitation.go | 30 +++++++---- ...esource_mongodbatlas_project_invitation.go | 16 +++--- website/docs/d/org_invitation.html.markdown | 24 ++++----- ...kdown => project_invitation.html.markdown} | 23 ++++----- website/docs/r/org_invitation.html.markdown | 51 +++++++++++-------- .../docs/r/project_invitation.html.markdown | 27 +++++----- 8 files changed, 108 insertions(+), 78 deletions(-) rename website/docs/d/{project_initiation.html.markdown => project_invitation.html.markdown} (57%) diff --git a/mongodbatlas/data_source_mongodbatlas_org_invitation.go b/mongodbatlas/data_source_mongodbatlas_org_invitation.go index 658f45fda4..c2c5bd0c4f 100644 --- a/mongodbatlas/data_source_mongodbatlas_org_invitation.go +++ b/mongodbatlas/data_source_mongodbatlas_org_invitation.go @@ -36,9 +36,16 @@ func dataSourceMongoDBAtlasOrgInvitation() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "teams_ids": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "roles": { Type: schema.TypeSet, - Optional: true, + Computed: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -83,6 +90,10 @@ func dataSourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Reso return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Organization Invitation (%s): %w", d.Id(), err)) } + if err := d.Set("teams_ids", orgInvitation.TeamIDs); err != nil { + return diag.FromErr(fmt.Errorf("error getting `teams_ids` for Organization Invitation (%s): %w", d.Id(), err)) + } + if err := d.Set("roles", orgInvitation.Roles); err != nil { return diag.FromErr(fmt.Errorf("error getting `roles` for Organization Invitation (%s): %w", d.Id(), err)) } diff --git a/mongodbatlas/data_source_mongodbatlas_project_invitation.go b/mongodbatlas/data_source_mongodbatlas_project_invitation.go index 88b4dca08f..ddde6dce76 100644 --- a/mongodbatlas/data_source_mongodbatlas_project_invitation.go +++ b/mongodbatlas/data_source_mongodbatlas_project_invitation.go @@ -38,7 +38,7 @@ func dataSourceMongoDBAtlasProjectInvitation() *schema.Resource { }, "roles": { Type: schema.TypeSet, - Optional: true, + Computed: true, Elem: &schema.Schema{ Type: schema.TypeString, }, diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index cfd28d8435..4c70ab642b 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "net/http" "regexp" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -27,7 +26,6 @@ func resourceMongoDBAtlasOrgInvitation() *schema.Resource { "org_id": { Type: schema.TypeString, Required: true, - ForceNew: true, }, "username": { Type: schema.TypeString, @@ -46,6 +44,17 @@ func resourceMongoDBAtlasOrgInvitation() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "inviter_username": { + Type: schema.TypeString, + Computed: true, + }, + "teams_ids": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, "roles": { Type: schema.TypeSet, Required: true, @@ -105,6 +114,14 @@ func resourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Resour return diag.FromErr(fmt.Errorf("error getting `created_at` for Organization Invitation (%s): %w", d.Id(), err)) } + if err := d.Set("inviter_username", orgInvitation.InviterUsername); err != nil { + return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Organization Invitation (%s): %w", d.Id(), err)) + } + + if err := d.Set("teams_ids", orgInvitation.TeamIDs); err != nil { + return diag.FromErr(fmt.Errorf("error getting `teams_ids` for Organization Invitation (%s): %w", d.Id(), err)) + } + if err := d.Set("roles", orgInvitation.Roles); err != nil { return diag.FromErr(fmt.Errorf("error getting `roles` for Organization Invitation (%s): %w", d.Id(), err)) } @@ -125,17 +142,12 @@ func resourceMongoDBAtlasOrgInvitationCreate(ctx context.Context, d *schema.Reso invitationReq := &matlas.Invitation{ Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), + TeamIDs: createOrgStringListFromSetSchema(d.Get("teams_ids").(*schema.Set)), Username: d.Get("username").(string), } - invitationRes, resp, err := conn.Organizations.InviteUser(ctx, orgID, invitationReq) + invitationRes, _, err := conn.Organizations.InviteUser(ctx, orgID, invitationReq) if err != nil { - // case 404 - // deleted in the backend case - if resp != nil && resp.StatusCode == http.StatusNotFound { - d.SetId("") - return nil - } return diag.FromErr(fmt.Errorf("error creating Organization invitation for user %s: %w", d.Get("username").(string), err)) } diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation.go b/mongodbatlas/resource_mongodbatlas_project_invitation.go index ad32482dc8..6f6fd10e2e 100644 --- a/mongodbatlas/resource_mongodbatlas_project_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_project_invitation.go @@ -45,6 +45,10 @@ func resourceMongoDBAtlasProjectInvitation() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "inviter_username": { + Type: schema.TypeString, + Computed: true, + }, "roles": { Type: schema.TypeSet, Required: true, @@ -104,6 +108,10 @@ func resourceMongoDBAtlasProjectInvitationRead(ctx context.Context, d *schema.Re return diag.FromErr(fmt.Errorf("error getting `created_at` for Project Invitation (%s): %w", d.Id(), err)) } + if err := d.Set("inviter_username", projectInvitation.InviterUsername); err != nil { + return diag.FromErr(fmt.Errorf("error getting `inviter_username` for Project Invitation (%s): %w", d.Id(), err)) + } + if err := d.Set("roles", projectInvitation.Roles); err != nil { return diag.FromErr(fmt.Errorf("error getting `roles` for Project Invitation (%s): %w", d.Id(), err)) } @@ -127,14 +135,8 @@ func resourceMongoDBAtlasProjectInvitationCreate(ctx context.Context, d *schema. Username: d.Get("username").(string), } - invitationRes, resp, err := conn.Projects.InviteUser(ctx, projectID, invitationReq) + invitationRes, _, err := conn.Projects.InviteUser(ctx, projectID, invitationReq) if err != nil { - // case 404 - // deleted in the backend case - if resp != nil && resp.StatusCode == http.StatusNotFound { - d.SetId("") - return nil - } return diag.FromErr(fmt.Errorf("error creating Project invitation for user %s: %w", d.Get("username").(string), err)) } diff --git a/website/docs/d/org_invitation.html.markdown b/website/docs/d/org_invitation.html.markdown index 5ba794933a..8328cd9b01 100644 --- a/website/docs/d/org_invitation.html.markdown +++ b/website/docs/d/org_invitation.html.markdown @@ -1,18 +1,16 @@ --- layout: "mongodbatlas" page_title: "MongoDB Atlas: org_invitation" -sidebar_current: "docs-mongodbatlas-organization-invitation" +sidebar_current: "docs-mongodbatlas-datasource-organization-invitation" description: |- - Provides a Atlas Organisation Invitation resource. + Provides an Atlas Organization Invitation. --- -# mongodbatlas_database_user +# mongodbatlas_org_invitation -`mongodbatlas_org_invitation` describes a Organisation Invitation resource. This represents an invitation for an Atlas User within an Atlas Organisation. +`mongodbatlas_org_invitation` describes an Organization Invitation. This represents an Invitation for an Atlas User within an Atlas Organizatiom. -Each invitation has a set of roles for an Atlas user within an organization. - --> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. +Each Invitation has a set of roles for an Atlas user within an organization. ## Example Usage @@ -31,17 +29,19 @@ data "mongodbatlas_org_user" "test" { ## Argument Reference -* `org_id` - (Required) The unique ID for the project to create the database user. +* `org_id` - (Required) The unique ID for the organization to create the Invitation. * `username` - (Required) The Atlas user's email address. ## Attributes Reference In addition to all arguments above, the following attributes are exported: -* `id` - The database user's name. -* `created_at` - The date and time the invitation was created -* `expires_at` - The date and time that the invitation will expire -* `invitation_id` - The identify of the invitation in Atlas +* `id` - Autogenerated Unique ID for this data source. +* `created_at` - The date and time the Invitation was created +* `expires_at` - The date and time that the Invitation will expire +* `invitation_id` - The identity of the Invitation in Atlas +* `inviter_username` - The username of the person creating the Invitation +* `teams_ids` - An array of team identifiers that the Atlas user has been invited to join * `roles` - List of user’s Atlas roles. The available options are: * ORG_OWNER * ORG_GROUP_CREATOR diff --git a/website/docs/d/project_initiation.html.markdown b/website/docs/d/project_invitation.html.markdown similarity index 57% rename from website/docs/d/project_initiation.html.markdown rename to website/docs/d/project_invitation.html.markdown index da7d86df03..884ed7509a 100644 --- a/website/docs/d/project_initiation.html.markdown +++ b/website/docs/d/project_invitation.html.markdown @@ -1,21 +1,19 @@ --- layout: "mongodbatlas" page_title: "MongoDB Atlas: project_invitation" -sidebar_current: "docs-mongodbatlas-project-invitation" +sidebar_current: "docs-mongodbatlas-datasource-project-invitation" description: |- - Provides a Atlas Project Invitation resource. + Provides an Atlas Project Invitation. --- # mongodbatlas_project_invitation -`mongodbatlas_project_invitation` describes a Project Invitation resource. This represents an invitation for an Atlas User within an Atlas Project. +`mongodbatlas_project_invitation` describes a Project Invitation. This represents an invitation for an Atlas User within an Atlas Project. -Each invitation for an Atlas user has a set of roles that provide access to a project in an organization. +Each Invitation for an Atlas User has a set of roles that provide access to a Project in an Organization. -> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. -~> **IMPORTANT:** All arguments including the password will be stored in the raw state as plain-text. [Read more about sensitive data in state.](https://www.terraform.io/docs/state/sensitive-data.html) - ## Example Usages ```hcl @@ -33,18 +31,19 @@ data "mongodbatlas_project_invitation" "test" { ## Argument Reference -* `project_id` - (Required) The unique ID for the project to create the database user. +* `project_id` - (Required) The unique ID for the Project to create the invitiation. * `username` - (Required) The Atlas user's email address. ## Attributes Reference In addition to all arguments above, the following attributes are exported: -* `id` - The database user's name. -* `created_at` - The date and time the invitation was created -* `expires_at` - The date and time that the invitation will expire -* `invitation_id` - The identify of the invitation in Atlas -* `roles` - List of user’s roles within the Atlas project. The available options are: +* `id` - Autogenerated Unique ID for this data source. +* `created_at` - The date and time the Invitation was created +* `expires_at` - The date and time that the Invitation will expire +* `invitation_id` - The identify of the Invitation in Atlas +* `inviter_username` - The username of the person creating the Invitation +* `roles` - List of User’s roles within the Atlas Project. The available options are: * GROUP_OWNER * GROUP_CLUSTER_MANAGER * GROUP_READ_ONLY diff --git a/website/docs/r/org_invitation.html.markdown b/website/docs/r/org_invitation.html.markdown index 84ccd0277d..77c4e78b91 100644 --- a/website/docs/r/org_invitation.html.markdown +++ b/website/docs/r/org_invitation.html.markdown @@ -1,18 +1,18 @@ --- layout: "mongodbatlas" page_title: "MongoDB Atlas: org_invitation" -sidebar_current: "docs-mongodbatlas-organization-invitation" +sidebar_current: "docs-mongodbatlas-resource-organization-invitation" description: |- - Provides a Atlas Organisation Invitation resource. + Provides an Atlas Organization Invitation resource. --- # mongodbatlas_org_invitation -`mongodbatlas_org_invitation` provides a Organisation Invitation resource. This represents an invitation for an Atlas User within an Atlas Organisation. +`mongodbatlas_org_invitation` provides an Organization Invitation resource. This represents an iIvitation for an Atlas User within an Atlas Organization. -Each invitation for an Atlas user has a set of roles that provide access to an organization. +Each Invitation for an Atlas User has a set of roles that provide access to an Organization. -The roles that can be utilised can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#organization-roles), which map to: +The roles that can be utilized can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#organization-roles), which map to: * ORG_OWNER * ORG_GROUP_CREATOR @@ -20,33 +20,39 @@ The roles that can be utilised can be found in the [MongoDB Documentation](https * ORG_READ_ONLY * ORG_MEMBER --> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. - -~> **IMPORTANT:** All arguments including the password will be stored in the raw state as plain-text. [Read more about sensitive data in state.](https://www.terraform.io/docs/state/sensitive-data.html) - ## Example Usages ```hcl -resource "mongodbatlas_org_invitation" "test" { - username = "test-acc-username" +resource "mongodbatlas_org_invitation" "test0" { + username = "test0-acc-username" org_id = "" roles = [ "GROUP_DATA_ACCESS_READ_WRITE" ] } ``` ```hcl -resource "mongodbatlas_org_invitation" "test" { - username = "test-acc-username" +resource "mongodbatlas_org_invitation" "test0" { + username = "test0-acc-username" org_id = "" roles = [ "GROUP_READ_ONLY", "GROUP_DATA_ACCESS_READ_ONLY" ] } ``` +```hcl +resource "mongodbatlas_org_invitation" "test1" { + username = "test1-acc-username" + org_id = "" + teams_ids = [ "", "" ] + roles = [ "GROUP_READ_ONLY" ] +} +``` + ## Argument Reference -* `project_id` - (Required) The unique ID for the project to create the database user. -* `username` - (Required) The Atlas user's email address. -* `roles` - (Required) List of user’s Atlas roles. The available options are: +* `org_id` - (Required) The unique ID for the Organization to create the Invitation. +* `username` - (Required) The Atlas User's email address. +* `teams_ids` - (Optional) An array of team identifiers that the Atlas User has been invited to join +* `roles` - (Required) List of User’s roles within the Atlas Organization. The available options are: * ORG_OWNER * ORG_GROUP_CREATOR * ORG_BILLING_ADMIN @@ -57,15 +63,16 @@ resource "mongodbatlas_org_invitation" "test" { In addition to all arguments above, the following attributes are exported: -* `id` - The database user's name. -* `created_at` - The date and time the invitation was created -* `expires_at` - The date and time that the invitation will expire -* `invitation_id` - The identify of the invitation in Atlas +* `id` - Autogenerated Unique ID for this resource. +* `created_at` - The date and time the Invitation was created +* `expires_at` - The date and time that the Invitation will expire +* `invitation_id` - The identity of the Invitation in Atlas +* `inviter_username` - The username of the person creating the Invitation ## Import -Organisations Invitations can be imported using organization ID and username (email address), in the format `org_id`-`username`, e.g. +Organisations Invitations can be imported using organization identifier and username (email address), in the format `org_id`-`username`, e.g. ``` -$ terraform import mongodbatlas_org_invitation.my_user 1112222b3bf99403840e8934-my_user +$ terraform import mongodbatlas_org_invitation.my_user 1112222b3bf99403840e8934-my_user@mongodb.com ``` diff --git a/website/docs/r/project_invitation.html.markdown b/website/docs/r/project_invitation.html.markdown index 9104903575..78bc8d7d4d 100644 --- a/website/docs/r/project_invitation.html.markdown +++ b/website/docs/r/project_invitation.html.markdown @@ -3,14 +3,14 @@ layout: "mongodbatlas" page_title: "MongoDB Atlas: project_invitation" sidebar_current: "docs-mongodbatlas-resource-project-invitation" description: |- - Provides a Atlas Project Invitation resource. + Provides an Atlas Project Invitation resource. --- # mongodbatlas_project_invitation -`mongodbatlas_project_invitation` provides a Project Invitation resource. This represents an invitation for an Atlas User within an Atlas Project. +`mongodbatlas_project_invitation` provides a Project Invitation resource. This represents an Invitation for an Atlas User within an Atlas Project. -Each invitation for an Atlas user has a set of roles that provide access to a project in an organization. +Each Invitation for an Atlas User has a set of roles that provide access to a Project in an Organization. The roles that can be utilised can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#project-roles), which map to: @@ -23,8 +23,6 @@ The roles that can be utilised can be found in the [MongoDB Documentation](https -> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. -~> **IMPORTANT:** All arguments including the password will be stored in the raw state as plain-text. [Read more about sensitive data in state.](https://www.terraform.io/docs/state/sensitive-data.html) - ## Example Usages ```hcl @@ -45,9 +43,9 @@ resource "mongodbatlas_project_invitation" "test" { ## Argument Reference -* `project_id` - (Required) The unique ID for the project to create the database user. -* `username` - (Required) The Atlas user's email address. -* `roles` - (Required) List of user’s roles within the Atlas project. The available options are: +* `project_id` - (Required) The unique ID for the Project to create the Invitation. +* `username` - (Required) The Atlas User's email address. +* `roles` - (Required) List of User’s roles within the Atlas Project. The available options are: * GROUP_OWNER * GROUP_CLUSTER_MANAGER * GROUP_READ_ONLY @@ -59,15 +57,16 @@ resource "mongodbatlas_project_invitation" "test" { In addition to all arguments above, the following attributes are exported: -* `id` - The database user's name. -* `created_at` - The date and time the invitation was created -* `expires_at` - The date and time that the invitation will expire -* `invitation_id` - The identify of the invitation in Atlas +* `id` - Autogenerated Unique ID for this resource. +* `created_at` - The date and time the Invitation was created +* `expires_at` - The date and time that the Invitation will expire +* `invitation_id` - The identify of the Invitation in Atlas +* `inviter_username` - The username of the person creating the Invitation ## Import -Projects Invitations can be imported using project ID and username (email address), in the format `project_id`-`username`, e.g. +Projects Invitations can be imported using Project ID and username (email address), in the format `project_id`-`username`, e.g. ``` -$ terraform import mongodbatlas_project_invitation.my_user 1112222b3bf99403840e8934-my_user +$ terraform import mongodbatlas_project_invitation.my_user 1112222b3bf99403840e8934-my_user@mongodb.com ``` From 07369053e4eb74ae6901f6f782a6ac0042e9ac25 Mon Sep 17 00:00:00 2001 From: beergeek Date: Mon, 4 Oct 2021 11:15:49 +1100 Subject: [PATCH 12/16] Fix conflict --- mongodbatlas/resource_mongodbatlas_org_invitation.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index 9e5b67ced6..59cb72be2a 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -141,8 +141,8 @@ func resourceMongoDBAtlasOrgInvitationCreate(ctx context.Context, d *schema.Reso orgID := d.Get("org_id").(string) invitationReq := &matlas.Invitation{ - Roles: createOrgStringListFromSetSchema(d.Get("roles").(*schema.Set)), - TeamIDs: createOrgStringListFromSetSchema(d.Get("teams_ids").(*schema.Set)), + Roles: expandStringListFromSetSchema(d.Get("roles").(*schema.Set)), + TeamIDs: expandStringListFromSetSchema(d.Get("teams_ids").(*schema.Set)), Username: d.Get("username").(string), } From fbeb495a1624fefa1b62f90d2c3920746b7ac914 Mon Sep 17 00:00:00 2001 From: beergeek Date: Thu, 21 Oct 2021 13:48:11 +1100 Subject: [PATCH 13/16] Fix context and spelling --- website/docs/r/org_invitation.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/r/org_invitation.html.markdown b/website/docs/r/org_invitation.html.markdown index 77c4e78b91..8236e64abc 100644 --- a/website/docs/r/org_invitation.html.markdown +++ b/website/docs/r/org_invitation.html.markdown @@ -8,7 +8,7 @@ description: |- # mongodbatlas_org_invitation -`mongodbatlas_org_invitation` provides an Organization Invitation resource. This represents an iIvitation for an Atlas User within an Atlas Organization. +`mongodbatlas_org_invitation` provides an Organization Invitation resource. This represents an invitation for an Atlas User within an Atlas Organization. Each Invitation for an Atlas User has a set of roles that provide access to an Organization. @@ -26,7 +26,7 @@ The roles that can be utilized can be found in the [MongoDB Documentation](https resource "mongodbatlas_org_invitation" "test0" { username = "test0-acc-username" org_id = "" - roles = [ "GROUP_DATA_ACCESS_READ_WRITE" ] + roles = [ "ORG_OWNER" ] } ``` @@ -34,7 +34,7 @@ resource "mongodbatlas_org_invitation" "test0" { resource "mongodbatlas_org_invitation" "test0" { username = "test0-acc-username" org_id = "" - roles = [ "GROUP_READ_ONLY", "GROUP_DATA_ACCESS_READ_ONLY" ] + roles = [ "ORG_MEMBER", "ORG_BILLING_ADMIN" ] } ``` @@ -43,7 +43,7 @@ resource "mongodbatlas_org_invitation" "test1" { username = "test1-acc-username" org_id = "" teams_ids = [ "", "" ] - roles = [ "GROUP_READ_ONLY" ] + roles = [ "ORG_MEMBER" ] } ``` From d26156f421e7fbfe961182e9d2569ce74de4057c Mon Sep 17 00:00:00 2001 From: beergeek Date: Thu, 28 Oct 2021 15:10:37 +1100 Subject: [PATCH 14/16] Fix spelling and grammar as advised --- website/docs/d/org_invitation.html.markdown | 26 ++++++++--------- .../docs/d/project_invitation.html.markdown | 28 +++++++++---------- website/docs/r/org_invitation.html.markdown | 28 +++++++++---------- .../docs/r/project_invitation.html.markdown | 20 ++++++------- 4 files changed, 49 insertions(+), 53 deletions(-) diff --git a/website/docs/d/org_invitation.html.markdown b/website/docs/d/org_invitation.html.markdown index 8328cd9b01..b01b16c668 100644 --- a/website/docs/d/org_invitation.html.markdown +++ b/website/docs/d/org_invitation.html.markdown @@ -8,9 +8,7 @@ description: |- # mongodbatlas_org_invitation -`mongodbatlas_org_invitation` describes an Organization Invitation. This represents an Invitation for an Atlas User within an Atlas Organizatiom. - -Each Invitation has a set of roles for an Atlas user within an organization. +`mongodbatlas_org_invitation` describes an invitation for a user to join an Atlas organization. ## Example Usage @@ -29,24 +27,24 @@ data "mongodbatlas_org_user" "test" { ## Argument Reference -* `org_id` - (Required) The unique ID for the organization to create the Invitation. -* `username` - (Required) The Atlas user's email address. +* `org_id` - (Required) Unique 24-hexadecimal digit string that identifies the organization to which you invited the user. +* `username` - (Required) Email address of the invited user. This is the address to which Atlas sends the invite. If the user accepts the invitation, they log in to Atlas with this username. ## Attributes Reference -In addition to all arguments above, the following attributes are exported: +In addition to the arguments, this data source exports the following attributes: -* `id` - Autogenerated Unique ID for this data source. -* `created_at` - The date and time the Invitation was created -* `expires_at` - The date and time that the Invitation will expire -* `invitation_id` - The identity of the Invitation in Atlas -* `inviter_username` - The username of the person creating the Invitation -* `teams_ids` - An array of team identifiers that the Atlas user has been invited to join -* `roles` - List of user’s Atlas roles. The available options are: +* `id` - Autogenerated unique string that identifies this data source. +* `created_at` - Timestamp in ISO 8601 date and time format in UTC when Atlas sent the invitation. +* `expires_at` - Timestamp in ISO 8601 date and time format in UTC when the invitation expires. Users have 30 days to accept an invitation. +* `invitation_id` - Unique 24-hexadecimal digit string that identifies the invitation in Atlas. +* `inviter_username` - Atlas user who invited `username` to the organization. +* `teams_ids` - An array of unique 24-hexadecimal digit strings that identify the teams that the user was invited to join. +* `roles` - Atlas roles to assign to the invited user. If the user accepts the invitation, Atlas assigns these roles to them. The following options are available: * ORG_OWNER * ORG_GROUP_CREATOR * ORG_BILLING_ADMIN * ORG_READ_ONLY * ORG_MEMBER -See [MongoDB Atlas API](https://docs.atlas.mongodb.com/reference/api/organization-get-one-invitation/) Documentation for more information. \ No newline at end of file +See the [MongoDB Atlas Administration API](https://docs.atlas.mongodb.com/reference/api/organization-get-one-invitation/) documentation for more information. \ No newline at end of file diff --git a/website/docs/d/project_invitation.html.markdown b/website/docs/d/project_invitation.html.markdown index 884ed7509a..5ca707675a 100644 --- a/website/docs/d/project_invitation.html.markdown +++ b/website/docs/d/project_invitation.html.markdown @@ -3,16 +3,14 @@ layout: "mongodbatlas" page_title: "MongoDB Atlas: project_invitation" sidebar_current: "docs-mongodbatlas-datasource-project-invitation" description: |- - Provides an Atlas Project Invitation. + Provides an Atlas project invitation. --- # mongodbatlas_project_invitation -`mongodbatlas_project_invitation` describes a Project Invitation. This represents an invitation for an Atlas User within an Atlas Project. +`mongodbatlas_project_invitation` describes an invitation to a user to join an Atlas project. -Each Invitation for an Atlas User has a set of roles that provide access to a Project in an Organization. - --> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. +-> **NOTE:** Groups and projects are synonymous terms. You may find GROUP-ID in the official documentation. ## Example Usages @@ -31,19 +29,19 @@ data "mongodbatlas_project_invitation" "test" { ## Argument Reference -* `project_id` - (Required) The unique ID for the Project to create the invitiation. -* `username` - (Required) The Atlas user's email address. +* `project_id` - (Required) Unique 24-hexadecimal digit string that identifies the project to which you invited the user. +* `username` - (Required) Email address of the invited user. This is the address to which Atlas sends the invite. If the user accepts the invitation, they log in to Atlas with this username. ## Attributes Reference -In addition to all arguments above, the following attributes are exported: +In addition to the arguments, this data source exports the following attributes: -* `id` - Autogenerated Unique ID for this data source. -* `created_at` - The date and time the Invitation was created -* `expires_at` - The date and time that the Invitation will expire -* `invitation_id` - The identify of the Invitation in Atlas -* `inviter_username` - The username of the person creating the Invitation -* `roles` - List of User’s roles within the Atlas Project. The available options are: +* `id` - Autogenerated unique string that identifies this data source. +* `created_at` - Timestamp in ISO 8601 date and time format in UTC when Atlas sent the invitation. +* `expires_at` - Timestamp in ISO 8601 date and time format in UTC when the invitation expires. Users have 30 days to accept an invitation. +* `invitation_id` - Unique 24-hexadecimal digit string that identifies the invitation in Atlas. +* `inviter_username` - Atlas user who invited `username` to the project. +* `roles` - Atlas roles to assign to the invited user. If the user accepts the invitation, Atlas assigns these roles to them. The following options are available: * GROUP_OWNER * GROUP_CLUSTER_MANAGER * GROUP_READ_ONLY @@ -51,4 +49,4 @@ In addition to all arguments above, the following attributes are exported: * GROUP_DATA_ACCESS_READ_WRITE * GROUP_DATA_ACCESS_READ_ONLY -See [MongoDB Atlas API](https://docs.atlas.mongodb.com/reference/user-roles/#project-roles) Documentation for more information. \ No newline at end of file +See the [MongoDB Atlas Administration API](https://docs.atlas.mongodb.com/reference/api/project-get-one-invitation/) documentation for more information. \ No newline at end of file diff --git a/website/docs/r/org_invitation.html.markdown b/website/docs/r/org_invitation.html.markdown index 8236e64abc..3fbf9aef3a 100644 --- a/website/docs/r/org_invitation.html.markdown +++ b/website/docs/r/org_invitation.html.markdown @@ -8,11 +8,11 @@ description: |- # mongodbatlas_org_invitation -`mongodbatlas_org_invitation` provides an Organization Invitation resource. This represents an invitation for an Atlas User within an Atlas Organization. +`mongodbatlas_org_invitation` invites a user to join an Atlas organization. -Each Invitation for an Atlas User has a set of roles that provide access to an Organization. +Each invitation for an Atlas user includes roles that Atlas grants the user when they accept the invitation. -The roles that can be utilized can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#organization-roles), which map to: +The [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#organization-roles) describes the roles a user can have, which map to: * ORG_OWNER * ORG_GROUP_CREATOR @@ -49,10 +49,10 @@ resource "mongodbatlas_org_invitation" "test1" { ## Argument Reference -* `org_id` - (Required) The unique ID for the Organization to create the Invitation. -* `username` - (Required) The Atlas User's email address. -* `teams_ids` - (Optional) An array of team identifiers that the Atlas User has been invited to join -* `roles` - (Required) List of User’s roles within the Atlas Organization. The available options are: +* `org_id` - (Required) Unique 24-hexadecimal digit string that identifies the organization to which you want to invite a user. +* `username` - (Required) Email address of the invited user. This is the address to which Atlas sends the invite. If the user accepts the invitation, they log in to Atlas with this username. +* `teams_ids` - (Optional) An array of unique 24-hexadecimal digit strings that identify the teams that the user was invited to join. +* `roles` - (Required) Atlas roles to assign to the invited user. If the user accepts the invitation, Atlas assigns these roles to them. The following options are available: * ORG_OWNER * ORG_GROUP_CREATOR * ORG_BILLING_ADMIN @@ -61,17 +61,17 @@ resource "mongodbatlas_org_invitation" "test1" { ## Attributes Reference -In addition to all arguments above, the following attributes are exported: +In addition to the arguments, this resource exports the following attributes: -* `id` - Autogenerated Unique ID for this resource. -* `created_at` - The date and time the Invitation was created -* `expires_at` - The date and time that the Invitation will expire -* `invitation_id` - The identity of the Invitation in Atlas -* `inviter_username` - The username of the person creating the Invitation +* `id` - Autogenerated unique string that identifies this resource. +* `created_at` - Timestamp in ISO 8601 date and time format in UTC when Atlas sent the invitation. +* `expires_at` - Timestamp in ISO 8601 date and time format in UTC when the invitation expires. Users have 30 days to accept an invitation. +* `invitation_id` - Unique 24-hexadecimal digit string that identifies the invitation in Atlas. +* `inviter_username` - Atlas user who invited `username` to the organization. ## Import -Organisations Invitations can be imported using organization identifier and username (email address), in the format `org_id`-`username`, e.g. +Import a user's invitation to an organization by separating the `org_id` and the `username` with a hyphen: ``` $ terraform import mongodbatlas_org_invitation.my_user 1112222b3bf99403840e8934-my_user@mongodb.com diff --git a/website/docs/r/project_invitation.html.markdown b/website/docs/r/project_invitation.html.markdown index 78bc8d7d4d..114e78dbf7 100644 --- a/website/docs/r/project_invitation.html.markdown +++ b/website/docs/r/project_invitation.html.markdown @@ -8,7 +8,7 @@ description: |- # mongodbatlas_project_invitation -`mongodbatlas_project_invitation` provides a Project Invitation resource. This represents an Invitation for an Atlas User within an Atlas Project. +`mongodbatlas_project_invitation` invites a user to join an Atlas project. Each Invitation for an Atlas User has a set of roles that provide access to a Project in an Organization. @@ -21,7 +21,7 @@ The roles that can be utilised can be found in the [MongoDB Documentation](https * GROUP_DATA_ACCESS_READ_WRITE * GROUP_DATA_ACCESS_READ_ONLY --> **NOTE:** Groups and projects are synonymous terms. You may find group_id in the official documentation. +-> **NOTE:** Groups and projects are synonymous terms. You may find GROUP-ID in the official documentation. ## Example Usages @@ -43,9 +43,9 @@ resource "mongodbatlas_project_invitation" "test" { ## Argument Reference -* `project_id` - (Required) The unique ID for the Project to create the Invitation. -* `username` - (Required) The Atlas User's email address. -* `roles` - (Required) List of User’s roles within the Atlas Project. The available options are: +* `project_id` - (Required) Unique 24-hexadecimal digit string that identifies the project to which you want to invite a user. +* `username` - (Required) Email address to which Atlas sent the invitation. The user uses this email address as their Atlas username if they accept this invitation. +* `roles` - (Required) List of Atlas roles to assign to the invited user. If the user accepts the invitation, Atlas assigns these roles to them. Atlas accepts the following roles: * GROUP_OWNER * GROUP_CLUSTER_MANAGER * GROUP_READ_ONLY @@ -58,14 +58,14 @@ resource "mongodbatlas_project_invitation" "test" { In addition to all arguments above, the following attributes are exported: * `id` - Autogenerated Unique ID for this resource. -* `created_at` - The date and time the Invitation was created -* `expires_at` - The date and time that the Invitation will expire -* `invitation_id` - The identify of the Invitation in Atlas -* `inviter_username` - The username of the person creating the Invitation +* `created_at` - Timestamp in ISO 8601 date and time format in UTC when Atlas sent the invitation. +* `expires_at` - Timestamp in ISO 8601 date and time format in UTC when the invitation expires. Users have 30 days to accept an invitation. +* `invitation_id` - Unique 24-hexadecimal digit string that identifies the invitation in Atlas. +* `inviter_username` - Atlas user who invited `username` to the project. ## Import -Projects Invitations can be imported using Project ID and username (email address), in the format `project_id`-`username`, e.g. +Import a user's invitation to a project by separating the `project_id` and the `username` with a hyphen: ``` $ terraform import mongodbatlas_project_invitation.my_user 1112222b3bf99403840e8934-my_user@mongodb.com From 2839fd09197e52a11f9e0641a0c99a2e19606f3c Mon Sep 17 00:00:00 2001 From: beergeek Date: Sat, 30 Oct 2021 08:35:23 +1100 Subject: [PATCH 15/16] Further spelling and grammatical fixes --- website/docs/r/project_invitation.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/project_invitation.html.markdown b/website/docs/r/project_invitation.html.markdown index 114e78dbf7..e30308f934 100644 --- a/website/docs/r/project_invitation.html.markdown +++ b/website/docs/r/project_invitation.html.markdown @@ -10,9 +10,9 @@ description: |- `mongodbatlas_project_invitation` invites a user to join an Atlas project. -Each Invitation for an Atlas User has a set of roles that provide access to a Project in an Organization. +Each invitation for an Atlas user includes roles that Atlas grants the user when they accept the invitation. -The roles that can be utilised can be found in the [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#project-roles), which map to: +The [MongoDB Documentation](https://docs.atlas.mongodb.com/reference/user-roles/#project-roles) describes the roles a user can have, which map to: * GROUP_OWNER * GROUP_CLUSTER_MANAGER From 04af7fd1d1df299798d8f067d673a39e024b9dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20L=C3=B3pez?= Date: Fri, 12 Nov 2021 19:38:36 -0700 Subject: [PATCH 16/16] refactor: fixed many bugs that couldn't be tested locally --- ...data_source_mongodbatlas_org_invitation.go | 2 +- ...source_mongodbatlas_org_invitation_test.go | 15 +++++---- ...ce_mongodbatlas_project_invitation_test.go | 15 +++++---- .../resource_mongodbatlas_org_invitation.go | 2 +- ...source_mongodbatlas_org_invitation_test.go | 33 +++++++++---------- ...ce_mongodbatlas_project_invitation_test.go | 16 ++++----- website/docs/d/org_invitation.html.markdown | 4 +-- .../docs/d/project_invitation.html.markdown | 4 +-- 8 files changed, 46 insertions(+), 45 deletions(-) diff --git a/mongodbatlas/data_source_mongodbatlas_org_invitation.go b/mongodbatlas/data_source_mongodbatlas_org_invitation.go index c2c5bd0c4f..14b015d052 100644 --- a/mongodbatlas/data_source_mongodbatlas_org_invitation.go +++ b/mongodbatlas/data_source_mongodbatlas_org_invitation.go @@ -70,7 +70,7 @@ func dataSourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Reso return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", d.Id(), err)) } - if err := d.Set("org_id", orgInvitation.GroupID); err != nil { + if err := d.Set("org_id", orgInvitation.OrgID); err != nil { return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", d.Id(), err)) } diff --git a/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go b/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go index 3cb84405ab..754afd3bb1 100644 --- a/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go +++ b/mongodbatlas/data_source_mongodbatlas_org_invitation_test.go @@ -12,7 +12,7 @@ import ( func TestAccDataSourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { var ( - dataSourceName = "mongodbatlas_org_invitations.test" + dataSourceName = "mongodbatlas_org_invitation.test" orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) initialRole = []string{"ORG_OWNER"} @@ -40,15 +40,16 @@ func TestAccDataSourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { func testAccDataSourceMongoDBAtlasOrgInvitationConfig(orgID, username string, roles []string) string { return fmt.Sprintf(` resource "mongodbatlas_org_invitation" "test" { - org_id = "%s" - username = "%s" - roles = %s + org_id = %[1]q + username = %[2]q + roles = ["%[3]s"] } data "mongodbatlas_org_invitation" "test" { - org_id = mongodbatlas_org_invitation.test.org_id - username = mongodbatlas_org_invitation.test.username + org_id = mongodbatlas_org_invitation.test.org_id + username = mongodbatlas_org_invitation.test.username + invitation_id = mongodbatlas_org_invitation.test.invitation_id }`, orgID, username, - strings.Join(roles, ","), + strings.Join(roles, `", "`), ) } diff --git a/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go b/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go index 9da850c1af..1b6eb26409 100644 --- a/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go +++ b/mongodbatlas/data_source_mongodbatlas_project_invitation_test.go @@ -12,7 +12,7 @@ import ( func TestAccDataSourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { var ( - dataSourceName = "mongodbatlas_project_invitations.test" + dataSourceName = "mongodbatlas_project_invitation.test" projectID = os.Getenv("MONGODB_ATLAS_PROJECT_ID") name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) initialRole = []string{"GROUP_OWNER"} @@ -40,15 +40,16 @@ func TestAccDataSourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { func testAccDataSourceMongoDBAtlasProjectInvitationConfig(projectID, username string, roles []string) string { return fmt.Sprintf(` resource "mongodbatlas_project_invitation" "test" { - project_id = "%s" - username = "%s" - roles = %s + project_id = %[1]q + username = %[2]q + roles = ["%[3]s"] } data "mongodbatlas_project_invitation" "test" { - project_id = mongodbatlas_project_invitation.test.projectID - username = mongodbatlas_project_invitation.test.username + project_id = mongodbatlas_project_invitation.test.project_id + username = mongodbatlas_project_invitation.test.username + invitation_id = mongodbatlas_project_invitation.test.invitation_id }`, projectID, username, - strings.Join(roles, ","), + strings.Join(roles, `", "`), ) } diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation.go b/mongodbatlas/resource_mongodbatlas_org_invitation.go index 59cb72be2a..c97458325e 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation.go @@ -98,7 +98,7 @@ func resourceMongoDBAtlasOrgInvitationRead(ctx context.Context, d *schema.Resour return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", d.Id(), err)) } - if err := d.Set("org_id", orgInvitation.GroupID); err != nil { + if err := d.Set("org_id", orgInvitation.OrgID); err != nil { return diag.FromErr(fmt.Errorf("error getting `username` for Organization Invitation (%s): %w", d.Id(), err)) } diff --git a/mongodbatlas/resource_mongodbatlas_org_invitation_test.go b/mongodbatlas/resource_mongodbatlas_org_invitation_test.go index b95a8c83dd..a32b8a0e07 100644 --- a/mongodbatlas/resource_mongodbatlas_org_invitation_test.go +++ b/mongodbatlas/resource_mongodbatlas_org_invitation_test.go @@ -16,7 +16,7 @@ import ( func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { var ( invitation matlas.Invitation - resourceName = "mongodbatlas_org_invitations.test" + resourceName = "mongodbatlas_org_invitation.test" orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) initialRole = []string{"ORG_OWNER"} @@ -36,9 +36,8 @@ func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(&invitation, initialRole), resource.TestCheckResourceAttrSet(resourceName, "org_id"), resource.TestCheckResourceAttrSet(resourceName, "username"), + resource.TestCheckResourceAttrSet(resourceName, "roles.#"), resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), - resource.TestCheckResourceAttr(resourceName, "username", name), - resource.TestCheckResourceAttr(resourceName, "roles.#", "1"), ), }, { @@ -49,7 +48,6 @@ func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { testAccCheckMongoDBAtlasOrgInvitationRoleAttribute(&invitation, updateRoles), resource.TestCheckResourceAttrSet(resourceName, "username"), resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), - resource.TestCheckResourceAttr(resourceName, "name", name), resource.TestCheckResourceAttr(resourceName, "roles.#", "2"), ), }, @@ -59,9 +57,10 @@ func TestAccResourceMongoDBAtlasOrgInvitation_basic(t *testing.T) { func TestAccResourceMongoDBAtlasOrgInvitation_importBasic(t *testing.T) { var ( - resourceName = "mongodbatlas_invitations.test" + resourceName = "mongodbatlas_org_invitation.test" orgID = os.Getenv("MONGODB_ATLAS_ORG_ID") - name = fmt.Sprintf("test-acc-%s", acctest.RandString(10)) + name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) + initialRole = []string{"ORG_OWNER"} ) resource.ParallelTest(t, resource.TestCase{ @@ -70,16 +69,16 @@ func TestAccResourceMongoDBAtlasOrgInvitation_importBasic(t *testing.T) { CheckDestroy: testAccCheckMongoDBAtlasOrgInvitationDestroy, Steps: []resource.TestStep{ { - Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, []string{"mongodbatlas.testing@gmail.com"}), + Config: testAccMongoDBAtlasOrgInvitationConfig(orgID, name, initialRole), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet(resourceName, "org_id"), - resource.TestCheckResourceAttrSet(resourceName, "name"), - resource.TestCheckResourceAttrSet(resourceName, "usernames.#"), + resource.TestCheckResourceAttrSet(resourceName, "username"), + resource.TestCheckResourceAttrSet(resourceName, "roles.#"), resource.TestCheckResourceAttrSet(resourceName, "invitation_id"), resource.TestCheckResourceAttr(resourceName, "org_id", orgID), - resource.TestCheckResourceAttr(resourceName, "name", name), - resource.TestCheckResourceAttr(resourceName, "usernames.#", "1"), + resource.TestCheckResourceAttr(resourceName, "username", name), + resource.TestCheckResourceAttr(resourceName, "roles.#", "1"), ), }, { @@ -179,17 +178,17 @@ func testAccCheckMongoDBAtlasOrgInvitationStateIDFunc(resourceName string) resou return "", fmt.Errorf("not found: %s", resourceName) } - return fmt.Sprintf("%s-%s", rs.Primary.Attributes["org_id"], rs.Primary.Attributes["invitation_id"]), nil + return fmt.Sprintf("%s-%s", rs.Primary.Attributes["org_id"], rs.Primary.Attributes["username"]), nil } } func testAccMongoDBAtlasOrgInvitationConfig(orgID, username string, roles []string) string { return fmt.Sprintf(` - resource "mongodbatlas_invitations" "test" { - org_id = "%s" - username = "%s" - roles = %s + resource "mongodbatlas_org_invitation" "test" { + org_id = %[1]q + username = %[2]q + roles = ["%[3]s"] }`, orgID, username, - strings.Join(roles, ","), + strings.Join(roles, `", "`), ) } diff --git a/mongodbatlas/resource_mongodbatlas_project_invitation_test.go b/mongodbatlas/resource_mongodbatlas_project_invitation_test.go index 95667207dc..068d919eff 100644 --- a/mongodbatlas/resource_mongodbatlas_project_invitation_test.go +++ b/mongodbatlas/resource_mongodbatlas_project_invitation_test.go @@ -16,7 +16,7 @@ import ( func TestAccResourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { var ( invitation matlas.Invitation - resourceName = "mongodbatlas_project_invitations.test" + resourceName = "mongodbatlas_project_invitation.test" projectID = os.Getenv("MONGODB_ATLAS_PROJECT_ID") name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) initialRole = []string{"GROUP_OWNER"} @@ -64,7 +64,7 @@ func TestAccResourceMongoDBAtlasProjectInvitation_basic(t *testing.T) { func TestAccResourceMongoDBAtlasProjectInvitation_importBasic(t *testing.T) { var ( - resourceName = "mongodbatlas_project_invitations.test" + resourceName = "mongodbatlas_project_invitation.test" projectID = os.Getenv("MONGODB_ATLAS_PROJECT_ID") name = fmt.Sprintf("test-acc-%s@mongodb.com", acctest.RandString(10)) initialRole = []string{"GROUP_OWNER"} @@ -187,17 +187,17 @@ func testAccCheckMongoDBAtlasProjectInvitationStateIDFunc(resourceName string) r return "", fmt.Errorf("not found: %s", resourceName) } - return fmt.Sprintf("%s-%s", rs.Primary.Attributes["org_id"], rs.Primary.Attributes["invitation_id"]), nil + return fmt.Sprintf("%s-%s", rs.Primary.Attributes["project_id"], rs.Primary.Attributes["username"]), nil } } func testAccMongoDBAtlasProjectInvitationConfig(projectID, username string, roles []string) string { return fmt.Sprintf(` - resource "mongodbatlas_invitations" "test" { - project_id = "%s" - username = "%s" - roles = %s + resource "mongodbatlas_project_invitation" "test" { + project_id = %[1]q + username = %[2]q + roles = ["%[3]s"] }`, projectID, username, - strings.Join(roles, ","), + strings.Join(roles, `", "`), ) } diff --git a/website/docs/d/org_invitation.html.markdown b/website/docs/d/org_invitation.html.markdown index b01b16c668..3c1eb468de 100644 --- a/website/docs/d/org_invitation.html.markdown +++ b/website/docs/d/org_invitation.html.markdown @@ -3,7 +3,7 @@ layout: "mongodbatlas" page_title: "MongoDB Atlas: org_invitation" sidebar_current: "docs-mongodbatlas-datasource-organization-invitation" description: |- - Provides an Atlas Organization Invitation. + Provides an Atlas Organization Invitation. --- # mongodbatlas_org_invitation @@ -29,6 +29,7 @@ data "mongodbatlas_org_user" "test" { * `org_id` - (Required) Unique 24-hexadecimal digit string that identifies the organization to which you invited the user. * `username` - (Required) Email address of the invited user. This is the address to which Atlas sends the invite. If the user accepts the invitation, they log in to Atlas with this username. +* `invitation_id` - (Required) Unique 24-hexadecimal digit string that identifies the invitation in Atlas. ## Attributes Reference @@ -37,7 +38,6 @@ In addition to the arguments, this data source exports the following attributes: * `id` - Autogenerated unique string that identifies this data source. * `created_at` - Timestamp in ISO 8601 date and time format in UTC when Atlas sent the invitation. * `expires_at` - Timestamp in ISO 8601 date and time format in UTC when the invitation expires. Users have 30 days to accept an invitation. -* `invitation_id` - Unique 24-hexadecimal digit string that identifies the invitation in Atlas. * `inviter_username` - Atlas user who invited `username` to the organization. * `teams_ids` - An array of unique 24-hexadecimal digit strings that identify the teams that the user was invited to join. * `roles` - Atlas roles to assign to the invited user. If the user accepts the invitation, Atlas assigns these roles to them. The following options are available: diff --git a/website/docs/d/project_invitation.html.markdown b/website/docs/d/project_invitation.html.markdown index 5ca707675a..e380b60099 100644 --- a/website/docs/d/project_invitation.html.markdown +++ b/website/docs/d/project_invitation.html.markdown @@ -3,7 +3,7 @@ layout: "mongodbatlas" page_title: "MongoDB Atlas: project_invitation" sidebar_current: "docs-mongodbatlas-datasource-project-invitation" description: |- - Provides an Atlas project invitation. + Provides an Atlas project invitation. --- # mongodbatlas_project_invitation @@ -31,6 +31,7 @@ data "mongodbatlas_project_invitation" "test" { * `project_id` - (Required) Unique 24-hexadecimal digit string that identifies the project to which you invited the user. * `username` - (Required) Email address of the invited user. This is the address to which Atlas sends the invite. If the user accepts the invitation, they log in to Atlas with this username. +* `invitation_id` - (Required) Unique 24-hexadecimal digit string that identifies the invitation in Atlas. ## Attributes Reference @@ -39,7 +40,6 @@ In addition to the arguments, this data source exports the following attributes: * `id` - Autogenerated unique string that identifies this data source. * `created_at` - Timestamp in ISO 8601 date and time format in UTC when Atlas sent the invitation. * `expires_at` - Timestamp in ISO 8601 date and time format in UTC when the invitation expires. Users have 30 days to accept an invitation. -* `invitation_id` - Unique 24-hexadecimal digit string that identifies the invitation in Atlas. * `inviter_username` - Atlas user who invited `username` to the project. * `roles` - Atlas roles to assign to the invited user. If the user accepts the invitation, Atlas assigns these roles to them. The following options are available: * GROUP_OWNER