diff --git a/.changelog/4400.txt b/.changelog/4400.txt new file mode 100644 index 0000000000..96dbd50cc6 --- /dev/null +++ b/.changelog/4400.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/mongodbatlas_advanced_cluster: Enables drift detection in `mongo_db_major_version` after performing an upgrade outside of Terraform +``` diff --git a/internal/service/advancedcluster/resource_compatibility_test.go b/internal/service/advancedcluster/resource_compatibility_test.go new file mode 100644 index 0000000000..3a914f83b3 --- /dev/null +++ b/internal/service/advancedcluster/resource_compatibility_test.go @@ -0,0 +1,42 @@ +package advancedcluster_test + +import ( + "testing" + + "github.com/mongodb/terraform-provider-mongodbatlas/internal/service/advancedcluster" + "github.com/stretchr/testify/assert" +) + +func TestAdvancedCluster_ShouldUsePreviousMongoDBMajorVersion(t *testing.T) { + testCases := []struct { + 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)) + }) + } +} diff --git a/internal/service/advancedcluster/resource_compatiblity.go b/internal/service/advancedcluster/resource_compatiblity.go index e12156dd41..b023cf06ef 100644 --- a/internal/service/advancedcluster/resource_compatiblity.go +++ b/internal/service/advancedcluster/resource_compatiblity.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" "go.mongodb.org/atlas-sdk/v20250312018/admin" @@ -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. + if beforeVersion != nil && afterVersion != nil && ShouldUsePreviousMongoDBMajorVersion(*beforeVersion, *afterVersion) { modelOut.MongoDBMajorVersion = types.StringPointerValue(beforeVersion) } overrideMapStringWithPrevStateValue(&modelIn.Labels, &modelOut.Labels) @@ -109,6 +112,18 @@ func overrideAttributesWithPrevStateValue(modelIn, modelOut *TFModel) { modelOut.UseEffectiveFields = modelIn.UseEffectiveFields } +func ShouldUsePreviousMongoDBMajorVersion(beforeVersion, afterVersion string) bool { + if beforeVersion == afterVersion { + return false + } + return majorComponent(beforeVersion) == majorComponent(afterVersion) +} + +func majorComponent(version string) string { + major, _, _ := strings.Cut(FormatMongoDBMajorVersion(version), ".") + return major +} + func overrideMapStringWithPrevStateValue(mapIn, mapOut *types.Map) { if mapIn == nil || mapOut == nil || len(mapOut.Elements()) > 0 { return