EC2 profile recreation breaks the functionality

Hello,
I recreated a VM profile which broke the functionality completely. Affected VMs were not able to access any AWS services until i manually removed and added back the profile.

I believe TF should have used replace-iam-instance-profile-association — AWS CLI 2.15.23 Command Reference but it probably did not…

Story:

  1. Initial working state:
    account has a module that creates and manages vm profile. The code is deployed and work properly.
  2. Change:
    the module is transitioned to be used as a sharable module across all accounts.
    The local code is updated to point to the “shareable” module.
    There are no other changes to the code.

During the code deployment:
role and profile are removed
role with the same name and policies, as well as profile with the same name and ARN are created.
3. Result:
vms lost access to sts service.

Is there something i’m doing incorrectly?

Code:
the original code, somewhat simplified:

resource "aws_iam_role" "VM_role" {
  name               = "DS_VM_role"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF

}

resource "aws_iam_instance_profile" "DS_VM_profile" {
  for_each = var.vm_profiles
  name = each.value.profile_name
  role = aws_iam_role.VM_role.name
}
....
resource "aws_iam_role_policy_attachment" "this" {
  role = aws_iam_role.VM_role.name
  for_each = tomap({
....
    "7" = "arn:aws:iam::aws:policy/AmazonKeyspacesFullAccess",
    "8" = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
  })
  policy_arn = each.value
}

That local code is replaced with:

module "vm_profile" {
  source                = "../../../Modules/config/ec2_profile/"
  vm_profiles           = var.vm_profiles
}

The execution log ( relevant parts):

Terraform will perform the following actions:

  # aws_iam_instance_profile.DS_VM_profile["profile0"] will be destroyed
  # (because aws_iam_instance_profile.DS_VM_profile is not in configuration)
  - resource "aws_iam_instance_profile" "DS_VM_profile" { ....
# aws_iam_role.VM_role will be destroyed
  # (because aws_iam_role.VM_role is not in configuration)
  - resource "aws_iam_role" "VM_role" {....
# aws_iam_role_policy_attachment.this["7"] will be destroyed
  # (because aws_iam_role_policy_attachment.this is not in configuration)
  - resource "aws_iam_role_policy_attachment" "this" {....

 # module.vm_profile.aws_iam_instance_profile.DS_VM_profile["profile0"] will be created
  + resource "aws_iam_instance_profile" "DS_VM_profile" {
      + arn         = (known after apply)
      + create_date = (known after apply)
      + id          = (known after apply)
      + name        = "DS_VM_profile"
      + name_prefix = (known after apply)
      + path        = "/"
      + role        = "DS_VM_role"
......

# module.vm_profile.aws_iam_role.VM_role will be created
  + resource "aws_iam_role" "VM_role" {
      + arn                   = (known after apply)
.....
# module.vm_profile.aws_iam_role_policy_attachment.this["7"] will be created
  + resource "aws_iam_role_policy_attachment" "this" { .....

as a workaround i used “moved”. and if i think about it. TF would not have enough information to determine that the 2 resources are the same…