Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/4400.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/mongodbatlas_advanced_cluster: Fixes perpetual plan drift on `mongo_db_major_version` after out-of-band major version upgrade
Comment thread
AgustinBettati marked this conversation as resolved.
Outdated
```
42 changes: 42 additions & 0 deletions internal/service/advancedcluster/resource_compatibility_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package advancedcluster_test
Comment thread
marcabreracast marked this conversation as resolved.

import (
"testing"

"github.com/mongodb/terraform-provider-mongodbatlas/internal/service/advancedcluster"
"github.com/stretchr/testify/assert"
)

func TestAdvancedCluster_ShouldUsePreviousMongoDBMajorVersion(t *testing.T) {
testCases := []struct {
Copy link
Copy Markdown

@augmentcode augmentcode Bot Apr 24, 2026

Choose a reason for hiding this comment

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

internal/service/advancedcluster/resource_compatibility_test.go:11 — The table covers major-change vs same-major outcomes, but it doesn’t exercise the beforeVersion == afterVersion early-return branch in ShouldUsePreviousMongoDBMajorVersion. Consider adding an explicit equality case to lock in that behavior.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

name string
before string
after string
expected bool
}{
{
name: "keeps previous version when only formatting differs",
before: "8",
after: "8.0",
expected: true,
},
{
name: "uses API value when major version actually changed",
before: "7.0",
after: "8.0",
expected: false,
},
{
name: "keeps previous version when minor version differs within same major",
before: "8.0",
after: "8.2",
expected: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.expected, advancedcluster.ShouldUsePreviousMongoDBMajorVersion(tc.before, tc.after))
})
}
}
17 changes: 16 additions & 1 deletion internal/service/advancedcluster/resource_compatiblity.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"strconv"
"strings"

"go.mongodb.org/atlas-sdk/v20250312018/admin"

Expand Down Expand Up @@ -94,7 +95,9 @@ func overrideAttributesWithPrevStateValue(modelIn, modelOut *TFModel) {
return
}
beforeVersion := conversion.NilForUnknown(modelIn.MongoDBMajorVersion, modelIn.MongoDBMajorVersion.ValueStringPointer())
if beforeVersion != nil && !modelIn.MongoDBMajorVersion.Equal(modelOut.MongoDBMajorVersion) {
afterVersion := conversion.NilForUnknown(modelOut.MongoDBMajorVersion, modelOut.MongoDBMajorVersion.ValueStringPointer())
// Only preserve prior state value for formatting differences (e.g. "8" vs "8.0"), not real version transitions.
Copy link
Copy Markdown

@augmentcode augmentcode Bot Apr 24, 2026

Choose a reason for hiding this comment

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

internal/service/advancedcluster/resource_compatiblity.go:99 — This comment says the override is only for formatting differences, but ShouldUsePreviousMongoDBMajorVersion also preserves the prior value when the minor version changes within the same major (e.g., CONTINUOUS returning 8.2). Consider clarifying the comment so future readers don’t assume this logic is formatting-only.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

if beforeVersion != nil && afterVersion != nil && ShouldUsePreviousMongoDBMajorVersion(*beforeVersion, *afterVersion) {
modelOut.MongoDBMajorVersion = types.StringPointerValue(beforeVersion)
}
overrideMapStringWithPrevStateValue(&modelIn.Labels, &modelOut.Labels)
Expand All @@ -109,6 +112,18 @@ func overrideAttributesWithPrevStateValue(modelIn, modelOut *TFModel) {
modelOut.UseEffectiveFields = modelIn.UseEffectiveFields
}

func ShouldUsePreviousMongoDBMajorVersion(beforeVersion, afterVersion string) bool {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This function helps preserve the prior state value when the major component is the same, which handles two cases:

  1. Formatting differences: user sets "8" but Atlas returns "8.0" which is the same version, but different format. This is to preserve SDKv2 behaviour
  2. version_release_system = "CONTINUOUS": Atlas can return a minor bump (e.g. "8.2") that is not user-controlled. Letting it through causes: provider produced an unexpected new value: .mongo_db_major_version: was cty.StringVal("8.0"), but now cty.StringVal("8.2"). `

The reason why step 2 is implemented, is to avoid unit test failure

if beforeVersion == afterVersion {
return false
}
return majorComponent(beforeVersion) == majorComponent(afterVersion)
}

func majorComponent(version string) string {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Users that have an outdate mongo_db_major_version value would now receive a non-empty plan (cases where major version upgrade was done outside of TF). Would confirm with Alex we are okay with this impact.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

q: Does version_release_system = "CONTINUOUS" only upgrade minor versions?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Both, per my understanding of the docs:

Latest Version With Auto Upgrades: If you set your cluster to this release option, it receives automatic upgrades to the latest available MongoDB major or minor version

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Okay, would make sure to test if an error is returned if version_release_system = "CONTINUOUS" and mongo_db_major_version attribute are used together (as per our docs). Using this combination would lead to non-empty plan once automatic major version upgrades are made.

major, _, _ := strings.Cut(FormatMongoDBMajorVersion(version), ".")
return major
}

func overrideMapStringWithPrevStateValue(mapIn, mapOut *types.Map) {
if mapIn == nil || mapOut == nil || len(mapOut.Elements()) > 0 {
return
Expand Down