-
Notifications
You must be signed in to change notification settings - Fork 205
feat: Add new singular data source mongodbatlas_cloud_user_project_assignment #3569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 18 commits
88fb77b
85de1f1
6e96ca3
57ebddb
e5fee7d
d262341
8705e44
19dc803
f7f8ed1
8ee68e8
4200827
10752de
0be853d
08dae31
78a17e0
47634de
3b40596
dc3404e
23632d3
e30f800
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:new-datasource | ||
data-source/mongodbatlas_cloud_user_project_assignment | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package clouduserprojectassignment | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/datasource" | ||
"github.com/mongodb/terraform-provider-mongodbatlas/internal/config" | ||
) | ||
|
||
var _ datasource.DataSource = &cloudUserProjectAssignmentDS{} | ||
var _ datasource.DataSourceWithConfigure = &cloudUserProjectAssignmentDS{} | ||
|
||
func DataSource() datasource.DataSource { | ||
return &cloudUserProjectAssignmentDS{ | ||
DSCommon: config.DSCommon{ | ||
DataSourceName: resourceName, | ||
}, | ||
} | ||
} | ||
|
||
type cloudUserProjectAssignmentDS struct { | ||
config.DSCommon | ||
} | ||
|
||
func (d *cloudUserProjectAssignmentDS) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { | ||
resp.Schema = dataSourceSchema() | ||
} | ||
|
||
func (d *cloudUserProjectAssignmentDS) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { | ||
var state TFModel | ||
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
connV2 := d.Client.AtlasV2 | ||
projectID := state.ProjectId.ValueString() | ||
userID := state.UserId.ValueString() | ||
username := state.Username.ValueString() | ||
|
||
if username == "" && userID == "" { | ||
resp.Diagnostics.AddError("invalid configuration", "either username or user_id must be provided") | ||
return | ||
} | ||
userResp, err := fetchProjectUser(ctx, connV2, projectID, userID, username) | ||
if err != nil { | ||
resp.Diagnostics.AddError(errorReadingUser, err.Error()) | ||
return | ||
} | ||
if userResp == nil { | ||
resp.State.RemoveResource(ctx) | ||
return | ||
} | ||
|
||
newCloudUserProjectAssignmentModel, diags := NewTFModel(ctx, projectID, userResp) | ||
if diags.HasError() { | ||
resp.Diagnostics.Append(diags...) | ||
return | ||
} | ||
resp.Diagnostics.Append(resp.State.Set(ctx, newCloudUserProjectAssignmentModel)...) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import ( | |
"context" | ||
"fmt" | ||
"os" | ||
"regexp" | ||
"strings" | ||
"testing" | ||
|
||
|
@@ -14,18 +15,24 @@ import ( | |
|
||
var resourceNamePending = "mongodbatlas_cloud_user_project_assignment.test_pending" | ||
var resourceNameActive = "mongodbatlas_cloud_user_project_assignment.test_active" | ||
var DSNameUsername = "data.mongodbatlas_cloud_user_project_assignment.testUsername" | ||
var DSNameUserID = "data.mongodbatlas_cloud_user_project_assignment.testUserID" | ||
|
||
func TestAccCloudUserProjectAssignmentRS_basic(t *testing.T) { | ||
func TestAccCloudUserProjectAssignment_basic(t *testing.T) { | ||
resource.ParallelTest(t, *basicTestCase(t)) | ||
} | ||
|
||
func TestAccCloudUserProjectAssignmentDS_error(t *testing.T) { | ||
resource.ParallelTest(t, *errorTestCase(t)) | ||
} | ||
|
||
func basicTestCase(t *testing.T) *resource.TestCase { | ||
t.Helper() | ||
|
||
orgID := os.Getenv("MONGODB_ATLAS_ORG_ID") | ||
activeUsername := os.Getenv("MONGODB_ATLAS_USERNAME_2") | ||
pendingUsername := acc.RandomEmail() | ||
projectName := acc.RandomName() | ||
projectID := acc.ProjectIDExecution(t) | ||
roles := []string{"GROUP_OWNER", "GROUP_CLUSTER_MANAGER"} | ||
updatedRoles := []string{"GROUP_OWNER", "GROUP_SEARCH_INDEX_EDITOR", "GROUP_READ_ONLY"} | ||
|
||
|
@@ -35,12 +42,12 @@ func basicTestCase(t *testing.T) *resource.TestCase { | |
CheckDestroy: checkDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: configBasic(orgID, pendingUsername, activeUsername, projectName, roles), | ||
Check: checks(pendingUsername, activeUsername, projectName, roles), | ||
Config: configBasic(orgID, pendingUsername, activeUsername, projectID, roles), | ||
Check: checks(pendingUsername, activeUsername, projectID, roles), | ||
}, | ||
{ | ||
Config: configBasic(orgID, pendingUsername, activeUsername, projectName, updatedRoles), | ||
Check: checks(pendingUsername, activeUsername, projectName, updatedRoles), | ||
Config: configBasic(orgID, pendingUsername, activeUsername, projectID, updatedRoles), | ||
Check: checks(pendingUsername, activeUsername, projectID, updatedRoles), | ||
}, | ||
{ | ||
ResourceName: resourceNamePending, | ||
|
@@ -94,7 +101,31 @@ func basicTestCase(t *testing.T) *resource.TestCase { | |
} | ||
} | ||
|
||
func configBasic(orgID, pendingUsername, activeUsername, projectName string, roles []string) string { | ||
func errorTestCase(t *testing.T) *resource.TestCase { | ||
t.Helper() | ||
orgID := os.Getenv("MONGODB_ATLAS_ORG_ID") | ||
projectID := acc.ProjectIDExecution(t) | ||
return &resource.TestCase{ | ||
PreCheck: func() { acc.PreCheckBasic(t) }, | ||
ProtoV6ProviderFactories: acc.TestAccProviderV6Factories, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: configError(orgID, projectID), | ||
ExpectError: regexp.MustCompile("either username or user_id must be provided"), | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func configError(orgID, projectID string) string { | ||
return fmt.Sprintf(` | ||
data "mongodbatlas_cloud_user_project_assignment" "test" { | ||
project_id = %[1]q | ||
} | ||
`, projectID, orgID) | ||
} | ||
|
||
func configBasic(orgID, pendingUsername, activeUsername, projectID string, roles []string) string { | ||
rolesStr := `"` + strings.Join(roles, `", "`) + `"` | ||
return fmt.Sprintf(` | ||
resource "mongodbatlas_project" "test" { | ||
|
@@ -104,26 +135,41 @@ func configBasic(orgID, pendingUsername, activeUsername, projectName string, rol | |
|
||
resource "mongodbatlas_cloud_user_project_assignment" "test_pending" { | ||
username = %[3]q | ||
project_id = mongodbatlas_project.test.id | ||
project_id = %[1]q | ||
roles = [%[5]s] | ||
} | ||
|
||
resource "mongodbatlas_cloud_user_project_assignment" "test_active" { | ||
username = %[4]q | ||
project_id = mongodbatlas_project.test.id | ||
project_id = %[1]q | ||
roles = [%[5]s] | ||
} | ||
|
||
data "mongodbatlas_cloud_user_project_assignment" "testUsername" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: stay consistent with format used for naming resources/data sources, for example, for resource you used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, changed it to be consistent |
||
project_id = %[1]q | ||
username = mongodbatlas_cloud_user_project_assignment.test_pending.username | ||
} | ||
|
||
data "mongodbatlas_cloud_user_project_assignment" "testUserID" { | ||
project_id = %[1]q | ||
user_id = mongodbatlas_cloud_user_project_assignment.test_pending.user_id | ||
}`, | ||
projectName, orgID, pendingUsername, activeUsername, rolesStr) | ||
projectID, orgID, pendingUsername, activeUsername, rolesStr) | ||
} | ||
|
||
func checks(pendingUsername, activeUsername, projectName string, roles []string) resource.TestCheckFunc { | ||
func checks(pendingUsername, activeUsername, projectID string, roles []string) resource.TestCheckFunc { | ||
checkFuncs := []resource.TestCheckFunc{ | ||
resource.TestCheckResourceAttr(resourceNamePending, "username", pendingUsername), | ||
resource.TestCheckResourceAttrSet(resourceNamePending, "project_id"), | ||
resource.TestCheckResourceAttr(resourceNamePending, "project_id", projectID), | ||
resource.TestCheckResourceAttr(resourceNamePending, "roles.#", fmt.Sprintf("%d", len(roles))), | ||
resource.TestCheckResourceAttr(resourceNameActive, "username", activeUsername), | ||
resource.TestCheckResourceAttrSet(resourceNameActive, "project_id"), | ||
resource.TestCheckResourceAttr(resourceNameActive, "project_id", projectID), | ||
resource.TestCheckResourceAttr(resourceNameActive, "roles.#", fmt.Sprintf("%d", len(roles))), | ||
resource.TestCheckResourceAttr(DSNameUserID, "username", pendingUsername), | ||
resource.TestCheckResourceAttrPair(DSNameUserID, "username", resourceNamePending, "username"), | ||
resource.TestCheckResourceAttrPair(DSNameUsername, "user_id", DSNameUserID, "user_id"), | ||
maastha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
resource.TestCheckResourceAttrPair(DSNameUsername, "project_id", DSNameUserID, "project_id"), | ||
resource.TestCheckResourceAttrPair(DSNameUsername, "roles.#", DSNameUserID, "roles.#"), | ||
} | ||
|
||
for _, role := range roles { | ||
|
@@ -132,6 +178,7 @@ func checks(pendingUsername, activeUsername, projectName string, roles []string) | |
resource.TestCheckTypeSetElemAttr(resourceNameActive, "roles.*", role), | ||
) | ||
} | ||
|
||
return resource.ComposeAggregateTestCheckFunc(checkFuncs...) | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.