Skip to content
Open
Show file tree
Hide file tree
Changes from all 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/45343.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_efs_file_system: Fix perpetual drift when `protection.replication_overwrite` is in `REPLICATING` state for replication destination file systems
```
21 changes: 21 additions & 0 deletions internal/service/efs/file_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ func resourceFileSystem() *schema.Resource {
ValidateFunc: validation.StringInSlice(enum.Slice(
awstypes.ReplicationOverwriteProtectionEnabled,
awstypes.ReplicationOverwriteProtectionDisabled,
awstypes.ReplicationOverwriteProtectionReplicating,
), false),
DiffSuppressFunc: SuppressReplicationOverwriteProtectionDiff,
},
},
},
Expand Down Expand Up @@ -609,3 +611,22 @@ func flattenFileSystemProtectionDescription(apiObject *awstypes.FileSystemProtec

return []any{tfMap}
}

func SuppressReplicationOverwriteProtectionDiff(k, old, new string, d *schema.ResourceData) bool {
// When a file system becomes a replication destination, AWS automatically
// sets replication_overwrite to "REPLICATING". This is a read-only state
// that cannot be changed while replication is active. AWS rejects all
// update attempts with: "ReplicationOverwriteProtection cannot be changed
// while the file system is a replication destination."
//
// Suppress diff when current state is REPLICATING to prevent perpetual
// drift and failed update attempts. When replication is removed, AWS
// automatically allows the protection setting to be changed again.

if old == string(awstypes.ReplicationOverwriteProtectionReplicating) {
// REPLICATING is AWS-managed and read-only; suppress any attempted change
return true
}

return false
}
71 changes: 71 additions & 0 deletions internal/service/efs/file_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,77 @@ func TestAccEFSFileSystem_protection(t *testing.T) {
})
}

func TestSuppressReplicationOverwriteProtectionDiff(t *testing.T) {
t.Parallel()

cases := []struct {
name string
old string
new string
expected bool
}{
{
name: "REPLICATING to DISABLED should be suppressed",
old: "REPLICATING",
new: "DISABLED",
expected: true,
},
{
name: "REPLICATING to ENABLED should be suppressed",
old: "REPLICATING",
new: "ENABLED",
expected: true,
},
{
name: "REPLICATING to REPLICATING should be suppressed",
old: "REPLICATING",
new: "REPLICATING",
expected: true,
},
{
name: "DISABLED to ENABLED should not be suppressed",
old: "DISABLED",
new: "ENABLED",
expected: false,
},
{
name: "ENABLED to DISABLED should not be suppressed",
old: "ENABLED",
new: "DISABLED",
expected: false,
},
{
name: "DISABLED to DISABLED should not be suppressed",
old: "DISABLED",
new: "DISABLED",
expected: false,
},
{
name: "ENABLED to REPLICATING should not be suppressed",
old: "ENABLED",
new: "REPLICATING",
expected: false,
},
{
name: "DISABLED to REPLICATING should not be suppressed",
old: "DISABLED",
new: "REPLICATING",
expected: false,
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

actual := tfefs.SuppressReplicationOverwriteProtectionDiff("protection.0.replication_overwrite", tc.old, tc.new, nil)
if actual != tc.expected {
t.Errorf("expected %v, got %v", tc.expected, actual)
}
})
}
}

func TestAccEFSFileSystem_availabilityZoneName(t *testing.T) {
ctx := acctest.Context(t)
var desc awstypes.FileSystemDescription
Expand Down
Loading