Call null_resources run a shell script after instance is modified

Have such a resources:

resource "aws_instance" "modify" {

  count = var.is_modify ? 1 : 0
  ami               = var.image
  instance_type     = var.instance_type

  tags = {
      Name = "${var.hostname}.fqdn.org"
  }
}

resource "null_resource" "modify" {

  provisioner "local-exec" {
  command = "scripts/failover-bootstrap.sh ${var.hostname}"
  on_failure = continue
  }
}

Using import option to get instance state
terraform import -var="region=eu-west-1" -var="modify=yes" module.aws-instance.aws_instance.modify id-1234abcd
and apply to change required attribute for example reduce instance_type
terraform apply -var="modify=true" -var="instance_type=t3.micro" -target=module.aws-instance.aws_instance.modify

The problem is to run a local script only after resource modification finished
Is there any way to call script after instance is modified ?

This is addressed in https://www.terraform.io/language/resources/provisioners/syntax; the answer is no, provisioners are only run for creation or destruction.

thanks @maxb for Your answer
but maybe there is an other workaround for this solution ?

Yes, writing your own orchestration for this outside of Terraform.

While we have mentioned in the past that Provisioners are a last resort, this is possible with the replace_triggered_by feature if the attribute being modified is not always known:

resource "aws_instance" "modify" {
  count = var.is_modify ? 1 : 0
  ami               = var.image

  instance_type     = var.instance_type
  tags = {
      Name = "${var.hostname}.fqdn.org"
  }
}

resource "null_resource" "modify" {
  provisioner "local-exec" {
    command = "scripts/failover-bootstrap.sh ${var.hostname}"
    on_failure = continue
  }
  lifecycle {
    replace_triggered_by = [aws_instance.modify]
  }
}

Otherwise, the changing attribute can be added to the null_resource triggers map, which will force replacement whenever it changes.

3 Likes

Wow, that is subtle.

Thanks @jbardin
perfect solution