Skip to content

[Bug]: Refresh state error with deleted database user outside of terraform #3063

@chagitgong

Description

@chagitgong

Is there an existing issue for this?

  • I have searched the existing issues

Provider Version

v1.26.1

Terraform Version

v1.6.6

Terraform Edition

Terraform Open Source (OSS)

Current Behavior

It looks like the refresh state doesn't handle well a diff between the current state and the desire state.
I have create a database user with the terraform provider and deleted it manually. Then, I have tried to re-create it using terraform and the apply failed with the following:

https://cloud.mongodb.com/api/atlas/v2/groups/XXXXXX/databaseUsers/$external/arn:aws:iam::XXXXXX:role%2FchagitNewTest
GET: HTTP 404 Not Found (Error code: "USERNAME_NOT_FOUND") Detail: No user with username arn:aws:iam::XXXX:role/chagitNewTest exists.
Reason: Not Found. Params: [arn:aws:iam::XXXXXX:role/chagitNewTest], BadRequestDetail: `

Upon investigating the code, I found the issue lies in the following snippet in terraform-provider-mongodbatlas/internal/service/databaseuser/resource_database_user.go:

dbUser, httpResponse, err := connV2.DatabaseUsersApi.GetDatabaseUser(ctx, projectID, authDatabaseName, username).Execute()
	if err != nil {
		// case 404
		// deleted in the backend case
		if httpResponse != nil && httpResponse.StatusCode == http.StatusNotFound {
			resp.State.RemoveResource(ctx)
			resp.Diagnostics.AddError("resource not found", err.Error())
			return
		}
		resp.Diagnostics.AddError("error getting database user information", err.Error())
		return
	}

Instead of setting the resource ID to an empty value (which would allow Terraform to recreate the resource), the code returns an error. This prevents Terraform from recreating the database user.
In other resources, this case is handled by setting an empty ID when the resource is not found. For example, in terraform-provider-mongodbatlas/internal/service/cluster/resource_cluster.go:

cluster, resp, err := connV2.ClustersApi.GetCluster(ctx, projectID, clusterName).Execute()
	if err != nil {
		if validate.StatusNotFound(resp) {
			d.SetId("")
			return nil
		}
		return diag.FromErr(fmt.Errorf(errorRead, clusterName, err))
	}

Here, the SetId("") call allows Terraform to handle the resource correctly and recreate it. A similar approach should be implemented for the database user resource.

Terraform configuration to reproduce the issue

terraform {
  required_providers {
    mongodbatlas = {
      source  = "mongodb/mongodbatlas"
      version = "~> 1.26.1"
    }
  }
  required_version = ">= 1.0.0"
}

provider "mongodbatlas" {
  public_key  = "XXXXXX"                                   # MongoDB Atlas public API key
  private_key = "XXXXXX"       # MongoDB Atlas private API key
}

# Create an IAM Role type MongoDB Atlas user
resource "mongodbatlas_database_user" "iam_user" {
  username           = "arn:aws:iam::XXXXXX:role/chagitNewTest"                      
  aws_iam_type       = "ROLE"                          
  project_id         = "XXXXXX"        
  auth_database_name = "$external"                         

  roles {
    role_name     = "readWriteAnyDatabase"             # MongoDB role to grant
    database_name = "admin"
  }

  labels {
    key   = "environment"
    value = "TEST"
  }

}

Steps To Reproduce

  1. Run terraform apply to the given configuration.
  2. Manually delete the created user.
  3. Try to recreate the user by running terraform apply again.

Logs

mongodbatlas_database_user.iam_user: Refreshing state... [id=XXXXXX]
╷
│ Error: resource not found
│ 
│   with mongodbatlas_database_user.iam_user,
│   on main.tf line 17, in resource "mongodbatlas_database_user" "iam_user":
│   17: resource "mongodbatlas_database_user" "iam_user" {
│ 
│ https://cloud.mongodb.com/api/atlas/v2/groups/XXXX/databaseUsers/$external/arn:aws:iam::XXXX:role%2FchagitNewTest
│ GET: HTTP 404 Not Found (Error code: "USERNAME_NOT_FOUND") Detail: No user with username arn:aws:iam::XXXXX:role/chagitNewTest exists.
│ Reason: Not Found. Params: [arn:aws:iam::XXXXX:role/chagitNewTest], BadRequestDetail: 

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions