Skip to content

Commit

Permalink
fix: avoid error when removing project api key assignment for deleted…
Browse files Browse the repository at this point in the history
… project (#1641)
  • Loading branch information
AgustinBettati committed Nov 21, 2023
1 parent bc33bf4 commit 58e939d
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 22 deletions.
47 changes: 25 additions & 22 deletions mongodbatlas/resource_mongodbatlas_project_api_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,12 @@ func resourceMongoDBAtlasProjectAPIKeyUpdate(ctx context.Context, d *schema.Reso
apiKeyID := ids["api_key_id"]

if d.HasChange("project_assignment") {
// Getting the current api_keys and the new api_keys with changes
newAPIKeys, changedAPIKeys, removedAPIKeys := getStateProjectAssignmentAPIKeys(d)
// Getting the changes to api key project assignments
newAssignments, changedAssignments, removedAssignments := getStateProjectAssignmentAPIKeys(d)

// Adding new api_keys into the project
if len(newAPIKeys) > 0 {
for _, apiKey := range newAPIKeys {
// Adding new projects assignments
if len(newAssignments) > 0 {
for _, apiKey := range newAssignments {
projectID := apiKey.(map[string]any)["project_id"].(string)
roles := expandStringList(apiKey.(map[string]any)["role_names"].(*schema.Set).List())
_, err := conn.ProjectAPIKeys.Assign(ctx, projectID, apiKeyID, &matlas.AssignAPIKey{
Expand All @@ -209,17 +209,20 @@ func resourceMongoDBAtlasProjectAPIKeyUpdate(ctx context.Context, d *schema.Reso
}
}

// Removing api_keys from the project
for _, apiKey := range removedAPIKeys {
// Removing projects assignments
for _, apiKey := range removedAssignments {
projectID := apiKey.(map[string]any)["project_id"].(string)
_, err := conn.ProjectAPIKeys.Unassign(ctx, projectID, apiKeyID)
if err != nil && strings.Contains(err.Error(), "GROUP_NOT_FOUND") {
continue // allows removing assignment for a project that has been deleted
}
if err != nil {
return diag.Errorf("error removing api_key(%s) from the project(%s): %s", apiKeyID, projectID, err)
}
}

// Updating the role names for the api_key
for _, apiKey := range changedAPIKeys {
// Updating the role names for the project assignments
for _, apiKey := range changedAssignments {
projectID := apiKey.(map[string]any)["project_id"].(string)
roles := expandStringList(apiKey.(map[string]any)["role_names"].(*schema.Set).List())
_, err := conn.ProjectAPIKeys.Assign(ctx, projectID, apiKeyID, &matlas.AssignAPIKey{
Expand Down Expand Up @@ -396,30 +399,30 @@ func newProjectAssignment(ctx context.Context, conn *matlas.Client, apiKeyID str
return results, nil
}

func getStateProjectAssignmentAPIKeys(d *schema.ResourceData) (newAPIKeys, changedAPIKeys, removedAPIKeys []any) {
currentAPIKeys, changes := d.GetChange("project_assignment")
func getStateProjectAssignmentAPIKeys(d *schema.ResourceData) (newAssignments, changedAssignments, removedAssignments []any) {
prevAssignments, currAssignments := d.GetChange("project_assignment")

rAPIKeys := currentAPIKeys.(*schema.Set).Difference(changes.(*schema.Set))
nAPIKeys := changes.(*schema.Set).Difference(currentAPIKeys.(*schema.Set))
changedAPIKeys = make([]any, 0)
rAssignments := prevAssignments.(*schema.Set).Difference(currAssignments.(*schema.Set))
nAssignments := currAssignments.(*schema.Set).Difference(prevAssignments.(*schema.Set))
changedAssignments = make([]any, 0)

for _, changed := range nAPIKeys.List() {
for _, removed := range rAPIKeys.List() {
for _, changed := range nAssignments.List() {
for _, removed := range rAssignments.List() {
if changed.(map[string]any)["project_id"] == removed.(map[string]any)["project_id"] {
rAPIKeys.Remove(removed)
rAssignments.Remove(removed)
}
}

for _, current := range currentAPIKeys.(*schema.Set).List() {
for _, current := range prevAssignments.(*schema.Set).List() {
if changed.(map[string]any)["project_id"] == current.(map[string]any)["project_id"] {
changedAPIKeys = append(changedAPIKeys, changed.(map[string]any))
nAPIKeys.Remove(changed)
changedAssignments = append(changedAssignments, changed.(map[string]any))
nAssignments.Remove(changed)
}
}
}

newAPIKeys = nAPIKeys.List()
removedAPIKeys = rAPIKeys.List()
newAssignments = nAssignments.List()
removedAssignments = rAssignments.List()

return
}
Expand Down
67 changes: 67 additions & 0 deletions mongodbatlas/resource_mongodbatlas_project_api_key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,37 @@ func TestAccConfigRSProjectAPIKey_RecreateWhenDeletedExternally(t *testing.T) {
})
}

func TestAccConfigRSProjectAPIKey_DeleteProjectAndAssignment(t *testing.T) {
var (
resourceName = "mongodbatlas_project_api_key.test"
orgID = os.Getenv("MONGODB_ATLAS_ORG_ID")
projectName = acctest.RandomWithPrefix("test-acc")
secondProjectName = acctest.RandomWithPrefix("test-acc")
description = fmt.Sprintf("%s-%s", "test-acc-project", acctest.RandString(5))
)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheckBasic(t) },
ProtoV6ProviderFactories: testAccProviderV6Factories,
CheckDestroy: testAccCheckMongoDBAtlasProjectAPIKeyDestroy,
Steps: []resource.TestStep{
{
Config: testAccMongoDBAtlasProjectAPIKeyConfigDeletedProjectAndAssignment(orgID, projectName, secondProjectName, description, true),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(resourceName, "project_assignment.0.project_id"),
resource.TestCheckResourceAttrSet(resourceName, "project_assignment.1.project_id"),
),
},
{
Config: testAccMongoDBAtlasProjectAPIKeyConfigDeletedProjectAndAssignment(orgID, projectName, secondProjectName, description, false),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(resourceName, "project_assignment.0.project_id"),
),
},
},
})
}

func deleteAPIKeyManually(orgID, descriptionPrefix string) error {
conn := testAccProviderSdkV2.Meta().(*MongoDBClient).Atlas
list, _, err := conn.APIKeys.List(context.Background(), orgID, &matlas.ListOptions{})
Expand Down Expand Up @@ -268,3 +299,39 @@ func testAccMongoDBAtlasProjectAPIKeyConfigMultiple(orgID, projectName, descript
}
`, orgID, projectName, description, roleNames)
}

func testAccMongoDBAtlasProjectAPIKeyConfigDeletedProjectAndAssignment(orgID, projectName, secondProjectName, description string, includeSecondProject bool) string {
var secondProject string
if includeSecondProject {
secondProject = fmt.Sprintf(`
resource "mongodbatlas_project" "project2" {
org_id = %[1]q
name = %[2]q
}`, orgID, secondProjectName)
}
var secondProjectAssignment string
if includeSecondProject {
secondProjectAssignment = `
project_assignment {
project_id = mongodbatlas_project.project2.id
role_names = ["GROUP_OWNER"]
}
`
}
return fmt.Sprintf(`
resource "mongodbatlas_project" "project1" {
org_id = %[1]q
name = %[2]q
}
%[3]s
resource "mongodbatlas_project_api_key" "test" {
project_id = mongodbatlas_project.project1.id
description = %[4]q
project_assignment {
project_id = mongodbatlas_project.project1.id
role_names = ["GROUP_OWNER"]
}
%[5]s
}
`, orgID, projectName, secondProject, description, secondProjectAssignment)
}

0 comments on commit 58e939d

Please sign in to comment.