Visitar URL original
fix: Treat 404 as success on resource delete operations by oarbusi · Pull Request #4784 · mongodb/terraform-provider-mongodbatlas · GitHub
Skip to content

fix: Treat 404 as success on resource delete operations - #4784

Open
oarbusi wants to merge 8 commits into
masterfrom
CLOUDP-453232
Open

oarbusi wants to merge 8 commits into
masterfrom
CLOUDP-453232

Conversation

@oarbusi

@oarbusi oarbusi commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Deleting a resource that is already gone from Atlas returned 404 and failed the whole run. The delete had already achieved its goal, so this is success, not failure, matching the HashiCorp recommendation for resource deletes.

Follow-up of #4777, which fixed mongodbatlas_database_user and added the shared helper (internal/common/deletenotfound.IsNotFound). This PR applies the same pattern to all remaining hand-written resources, and replaces ad-hoc 404 checks (manual validate.StatusNotFound blocks and string-matching) with the helper. The tolerated 404 case is logged so it can be observed in production.

Affected resources:

mongodbatlas_advanced_cluster, mongodbatlas_alert_configuration, mongodbatlas_auditing, mongodbatlas_backup_compliance_policy, mongodbatlas_cloud_backup_schedule, mongodbatlas_cloud_backup_snapshot, mongodbatlas_cloud_backup_snapshot_export_bucket, mongodbatlas_cloud_backup_snapshot_restore_job, mongodbatlas_cloud_provider_access_setup, mongodbatlas_cluster, mongodbatlas_cluster_outage_simulation, mongodbatlas_custom_db_role, mongodbatlas_database_user, mongodbatlas_encryption_at_rest_private_endpoint, mongodbatlas_event_trigger, mongodbatlas_federated_database_instance, mongodbatlas_federated_query_limit, mongodbatlas_federated_settings_identity_provider, mongodbatlas_federated_settings_org_config, mongodbatlas_federated_settings_org_role_mapping, mongodbatlas_flex_cluster, mongodbatlas_global_cluster_config, mongodbatlas_ldap_configuration, mongodbatlas_maintenance_window, mongodbatlas_network_peering, mongodbatlas_online_archive, mongodbatlas_organization, mongodbatlas_org_invitation, mongodbatlas_privatelink_endpoint, mongodbatlas_privatelink_endpoint_service, mongodbatlas_project, mongodbatlas_project_invitation, mongodbatlas_project_ip_access_list, mongodbatlas_project_service_account_access_list_entry, mongodbatlas_resource_policy, mongodbatlas_search_deployment, mongodbatlas_search_index, mongodbatlas_serverless_instance, mongodbatlas_service_account_access_list_entry, mongodbatlas_stream_instance, mongodbatlas_stream_privatelink_endpoint, mongodbatlas_stream_processor, mongodbatlas_stream_workspace, mongodbatlas_team_project_assignment

Not changed, on purpose:

  • No API call in delete: mongodbatlas_x509_authentication_database_user, mongodbatlas_ldap_verify, mongodbatlas_cloud_backup_snapshot_export_job
  • Delete goes through an update/toggle API, not a resource delete: mongodbatlas_custom_dns_configuration_cluster_aws, mongodbatlas_encryption_at_rest, mongodbatlas_private_endpoint_regional_mode
  • Already treat 404 as success (poll/retry swallows it): mongodbatlas_network_container, mongodbatlas_team, mongodbatlas_stream_connection
  • Legacy v1 SDK delete returns no HTTP response, so the guard cannot be applied: mongodbatlas_third_party_integration
  • Pre-existing bug kept as-is to avoid new error surface (only errors on 404 and swallows other errors); will be analyzed separately, similar to CLOUDP-437881: mongodbatlas_mongodb_employee_access_grant

Verified against the dev environment that a delete of a made-up resource under a real parent returns 404 for the affected resources above. Exceptions observed:

  • Org API key resources (mongodbatlas_api_key, mongodbatlas_project_api_key, mongodbatlas_access_list_api_key, mongodbatlas_api_key_project_assignment): the API returns 400 API_KEY_NOT_FOUND instead of 404 for a missing key (even on GET), so delete behavior does not change there. The guard is kept so these resources automatically treat the delete as success when/if the API is fixed.
  • mongodbatlas_push_based_log_export (deprecated): returns 400 PUSH_BASED_LOG_EXPORT_ALREADY_UNCONFIGURED when already unconfigured, so the guard does not change its behavior.
  • mongodbatlas_maintenance_window: resetting an unconfigured window returns 204, already a success.
  • mongodbatlas_stream_privatelink_endpoint: delete is accepted asynchronously with 202.

Link to any related issue(s):

Type of change:

  • Bug fix (non-breaking change which fixes an issue). Please, add the "bug" label to the PR.
  • New feature (non-breaking change which adds functionality). Please, add the "enhancement" label to the PR. A migration guide must be created or updated if the new feature will go in a major version.
  • Breaking change (fix or feature that would cause existing functionality to not work as expected). Please, add the "breaking change" label to the PR. A migration guide must be created or updated.
  • This change requires a documentation update
  • Documentation fix/enhancement

Required Checklist:

  • I have signed the MongoDB CLA
  • I have read the contributing guides
  • I have checked that this change does not generate any credentials and that they are NOT accidentally logged anywhere.
  • I have added tests that prove my fix is effective or that my feature works per HashiCorp requirements
  • I have added any necessary documentation (if appropriate)
  • I have run make fix and verified my code
  • If changes include deprecations or removals I have added appropriate changelog entries.
  • If changes include removal or addition of 3rd party GitHub actions, I updated our internal document. Reach out to the APIx Integration slack channel to get access to the internal document.

Further comments

A 404 can also mean a mistaken project ID or credentials scoped differently; previously the error surfaced that, now the resource is silently dropped from state and the mistake appears later as drift. This trade-off was accepted in the ticket triage ("we only turn failure into success operations"), and the tflog line makes the tolerated case observable.

Autogen resources already treat a 404 on delete as success by construction.

Deleting a resource that is already gone from Atlas returned 404 and
failed the whole run. The delete achieved its goal, so it now succeeds
and the resource is removed from state.

Applies the shared internal/common/deletenotfound helper to all
remaining hand-written resources, following up on database user.
@github-actions github-actions Bot added the bug label Oct 5, 2026
@oarbusi
oarbusi marked this pull request as ready for review October 6, 2026 15:50
@oarbusi
oarbusi requested review from a team as code owners October 6, 2026 15:50
Copilot AI balanced review requested due to automatic review settings October 6, 2026 15:50
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

APIx bot: a message has been sent to Docs Slack channel

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Legacy response dereferences can panic, and global cluster configuration deletion still fails on an earlier 404 path.

Review effort: Balanced
Findings: 2 High severity · 1 Medium severity · 1 Low severity

Open (4)
What changed in this PR

Extends idempotent delete handling across handwritten resources so Atlas 404 responses are treated as successful deletion.

Changes:

  • Applies the shared deletenotfound.IsNotFound helper to delete operations.
  • Replaces several ad-hoc 404 checks and adds observable logging.
  • Adds a consolidated bug-fix changelog entry.
File Description
.changelog/​4784.txt Documents affected resources.
internal/​service/​accesslistapikey/​resource.go Handles missing API-key access entries.
internal/​service/​advancedcluster/​common_admin_sdk.go Handles missing advanced clusters.
internal/​service/​alertconfiguration/​resource.go Handles missing alert configurations.
internal/​service/​apikey/​resource_api_key.go Handles missing API keys.
internal/​service/​apikeyprojectassignment/​resource.go Handles missing API-key assignments.
internal/​service/​auditing/​resource_auditing.go Handles missing auditing configuration.
internal/​service/​backupcompliancepolicy/​resource_backup_compliance_policy.go Handles missing compliance policy.
internal/​service/​cloudbackupschedule/​resource_cloud_backup_schedule.go Handles missing backup schedules.
internal/​service/​cloudbackupsnapshot/​resource.go Handles missing snapshots.
internal/​service/​cloudbackupsnapshotexportbucket/​resource_cloud_backup_snapshot_export_bucket.go Handles missing export buckets.
internal/​service/​cloudbackupsnapshotrestorejob/​resource_cloud_backup_snapshot_restore_job.go Handles missing restore jobs.
internal/​service/​cloudprovideraccess/​resource_cloud_provider_access_setup.go Handles missing provider access.
internal/​service/​cluster/​resource_cluster.go Handles missing legacy clusters.
internal/​service/​clusteroutagesimulation/​resource.go Handles missing outage simulations.
internal/​service/​customdbrole/​resource.go Handles missing custom roles.
internal/​service/​encryptionatrestprivateendpoint/​resource.go Handles missing private endpoints.
internal/​service/​eventtrigger/​resource_event_trigger.go Handles missing event triggers.
internal/​service/​federateddatabaseinstance/​resource_federated_database_instance.go Handles missing federated databases.
internal/​service/​federatedquerylimit/​resource_federated_query_limit.go Handles missing query limits.
internal/​service/​federatedsettingsidentityprovider/​resource_federated_settings_identity_provider.go Normalizes identity-provider 404 handling.
internal/​service/​federatedsettingsorgconfig/​resource_federated_settings_connected_org.go Handles missing organization configuration.
internal/​service/​federatedsettingsorgrolemapping/​resource_federated_settings_org_role_mapping.go Handles missing role mappings.
internal/​service/​flexcluster/​resource.go Handles missing flex clusters.
internal/​service/​globalclusterconfig/​resource_global_cluster_config.go Handles missing zone mappings.
internal/​service/​ldapconfiguration/​resource_ldap_configuration.go Handles missing LDAP configuration.
internal/​service/​maintenancewindow/​resource_maintenance_window.go Handles missing maintenance windows.
internal/​service/​mongodbemployeeaccessgrant/​resource.go Corrects employee-access deletion errors.
internal/​service/​networkpeering/​resource.go Handles missing peerings.
internal/​service/​onlinearchive/​resource.go Replaces string-based 404 detection.
internal/​service/​organization/​resource_organization.go Handles missing organizations.
internal/​service/​orginvitation/​resource_org_invitation.go Handles missing organization invitations.
internal/​service/​privatelinkendpoint/​resource.go Normalizes private-link 404 handling.
internal/​service/​privatelinkendpointservice/​resource.go Handles missing endpoint services.
internal/​service/​project/​resource_project.go Handles missing projects.
internal/​service/​projectapikey/​resource_project_api_key.go Handles missing project API keys.
internal/​service/​projectinvitation/​resource_project_invitation.go Handles missing project invitations.
internal/​service/​projectipaccesslist/​resource_project_ip_access_list.go Normalizes access-list 404 handling.
internal/​service/​projectserviceaccountaccesslistentry/​resource.go Handles missing project access entries.
internal/​service/​pushbasedlogexport/​resource.go Handles missing log-export configuration.
internal/​service/​resourcepolicy/​resource.go Handles missing resource policies.
internal/​service/​searchdeployment/​resource.go Handles missing search deployments.
internal/​service/​searchindex/​resource_search_index.go Handles missing search indexes.
internal/​service/​serverlessinstance/​resource_serverless_instance.go Handles missing serverless instances.
internal/​service/​serviceaccountaccesslistentry/​resource.go Handles missing organization access entries.
internal/​service/​streaminstance/​resource_stream_instance.go Handles missing stream instances.
internal/​service/​streamprivatelinkendpoint/​resource.go Handles missing stream private links.
internal/​service/​streamprocessor/​resource.go Handles missing stream processors.
internal/​service/​streamworkspace/​resource.go Handles missing stream workspaces.
internal/​service/​teamprojectassignment/​resource.go Normalizes team-assignment 404 handling.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/service/cluster/resource_cluster.go Outdated
Comment thread internal/service/eventtrigger/resource_event_trigger.go Outdated
Comment thread .changelog/4784.txt Outdated
@augmentcode

augmentcode Bot commented Oct 6, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: Makes handwritten resource deletes tolerate HTTP 404 when the Atlas resource is already absent.

  • Extends fix: Treat 404 as success on database user delete #4777's shared deletenotfound.IsNotFound handling to other resources.
  • Captures HTTP responses in SDKv2, Plugin Framework, and legacy SDK delete paths.
  • Replaces manual 404 checks and online-archive error-string matching.
  • Logs tolerated 404 responses through the shared helper.
  • Keeps error diagnostics for non-404 API responses.
  • Short-circuits already-missing export-bucket and push-based log-export deletes.
  • Corrects employee-access-grant delete error classification.
  • Adds a release note listing the affected resources.
Why: Deleting an already-absent resource should remove it from Terraform state rather than block destroy.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread internal/service/cluster/resource_cluster.go Outdated
Comment thread internal/service/searchdeployment/resource.go

@lmkerbey-mdb lmkerbey-mdb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Comment thread internal/service/mongodbemployeeaccessgrant/resource.go
@oarbusi

oarbusi commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator Author

Verified against cloud-dev that a DELETE of a made-up resource ID under a real parent returns 404 for the affected resources, validating the guard. Summary of exceptions:

  • Org API key resources (api_key, project_api_key, access_list_api_key, api_key_project_assignment): Atlas returns 400 API_KEY_NOT_FOUND for a missing key (even on GET) instead of 404, so behavior does not change there. The guard is kept so they automatically treat the delete as success once the API is fixed.
  • push_based_log_export (deprecated): 400 ALREADY_UNCONFIGURED when already unconfigured; guard is a no-op.
  • maintenance_window: reset of unconfigured window is 204, already success.
  • stream_privatelink_endpoint: delete accepted asynchronously (202).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants