Hi Terraform community
I have a requirement whereby I need to ensure that a datasource is re-read on terraform destroy prior to a destroy time remote-exec provisioner executing.
The datasource that i trigger in normal terraform apply and need to have re-triggered in terraform destroy is
After that datasource is triggered, I need the null_resource destroy time provisioner below to run.
My issue is that sometimes the datasource is read on destroy, other times not.
When it is read, I see in the logs on destroy something like …
[INFO] data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip: Reading...
[INFO] data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip: Read complete after 2s [id=ResourcemanagerPrivateEndpointReachableIpDataSource-3312716207]
resource "null_resource" "cleanup" {
depends_on = [time_sleep.wait_15_seconds_destroy_private_endpoint]
triggers = {
ip = data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip.ip_address
}
provisioner "remote-exec" {
when = destroy
connection {
agent = false
timeout = "3m"
host = self.triggers.ip
}
inline = [
"#!/bin/bash",
...
]
}
}
Is there anyway to ensure that a datasource is always re-read on destroy?
Terraform version is 1.5.x
I’ve tried adding depends_on dependencies to the ‘cleanup’ resource that require the datasource to be read, but unfortunately I don’t see datasource “Reading…” actions get triggered. Neither this worked …
resource "terraform_data" "reachable_ip_force_refresh" {
depends_on = [ null_resource.cleanup ]
triggers_replace = [
data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip.ip_address
]
provisioner "local-exec" {
command = "echo Reachable IP: ${data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip.ip_address}"
}
}
Nor this …
data "null_data_source" "reachable_ip" {
depends_on = [ data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip ]
inputs = {
ip = data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip.ip_address
}
}
resource "null_resource" "reachable_ip_force_refresh" {
depends_on = [ data.null_data_source.reachable_ip, null_resource.cleanup ]
triggers = {
always_run = timestamp()
}
provisioner "local-exec" {
command = "echo Reachable IP: ${data.null_data_source.reachable_ip.outputs["ip"]}"
}
}
IMO - looks to be some type of multi-threaded race
working one looks like
2025-04-15T13:30:46.078Z [TRACE] dag/walk: vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)" is waiting for "oci_resourcemanager_private_endpoint.operator_instance_private_endpoint (expand)"
2025-04-15T13:30:46.078Z [TRACE] dag/walk: vertex "null_resource.cleanup (expand)" is waiting for "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)"
2025-04-15T13:30:46.078Z [TRACE] dag/walk: vertex "output.reachable_ip (expand)" is waiting for "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)"
2025-04-15T13:30:47.373Z [TRACE] vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)": starting visit (*terraform.nodeExpandPlannableResource)
2025-04-15T13:30:47.373Z [TRACE] vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)": expanding dynamic subgraph
2025-04-15T13:30:47.373Z [TRACE] ResourceCountTransformer: adding data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip as *terraform.NodePlannableResourceInstance
data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip - *terraform.NodePlannableResourceInstance
2025-04-15T13:30:47.373Z [TRACE] NodeAbstractResourceInstance.AttachResourceState for data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip
2025-04-15T13:30:47.373Z [DEBUG] ReferenceTransformer: "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip" references: []
data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip - *terraform.NodePlannableResourceInstance
data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip - *terraform.NodePlannableResourceInstance
2025-04-15T13:30:47.373Z [TRACE] vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)": entering dynamic subgraph
2025-04-15T13:30:47.373Z [TRACE] vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip": starting visit (*terraform.NodePlannableResourceInstance)
2025-04-15T13:30:47.381Z [TRACE] readDataSource: Re-validating config for data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip
2025-04-15T13:30:47.389Z [TRACE] readDataSource: data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip configuration is complete, so reading from provider
failing one has no dag/walk statements and looks like …
2025-04-15T13:49:29.472Z [TRACE] vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)": starting visit (*terraform.nodeExpandPlannableResource)
2025-04-15T13:49:29.472Z [TRACE] vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)": expanding dynamic subgraph
2025-04-15T13:49:29.472Z [TRACE] ResourceCountTransformer: adding data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip as *terraform.NodePlannableResourceInstance
data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip - *terraform.NodePlannableResourceInstance
2025-04-15T13:49:29.472Z [DEBUG] Resource instance state not found for node "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip", instance data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip
2025-04-15T13:49:29.472Z [DEBUG] ReferenceTransformer: "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip" references: []
data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip - *terraform.NodePlannableResourceInstance
data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip - *terraform.NodePlannableResourceInstance
2025-04-15T13:49:29.472Z [TRACE] vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip (expand)": entering dynamic subgraph
2025-04-15T13:49:29.472Z [TRACE] vertex "data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip": starting visit (*terraform.NodePlannableResourceInstance)
2025-04-15T13:49:29.472Z [TRACE] planDataSource: data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip configuration not fully known yet, so deferring to apply phase
@jbardin @apparentlymart - Hi Guys, sorry for unsolicited contact. Any idea what could be going on here? thanks
Your log output has the reason why the data source isn’t being read:
data.oci_resourcemanager_private_endpoint_reachable_ip.operator_instance_private_endpoint_reachable_ip configuration not fully known yet
So something in that configuration isn’t known, so the data source cannot be read, and there would be no way to force that to always read in call cases. I don’t think that is really the underlying problem you’re having though, and it’s probably more related to the concept of a destroy provisioner in general.
The data stored in null_resource.cleanup
is always going to be the data which was last applied. Regardless of whether data.oci_resourcemanager_private_endpoint_reachable_ip
is read again or not, the prior state of null_resource.cleanup
doesn’t change because the only change that can result from a destroy plan is from the prior state to a null state.
Thanks James. I’ve tried so many combinations with depends_on and so forth to try and influence the sequencing and behaviour. At one point for example I was using a random function as a suffix in resource naming, and removing this and making resource names static appeared to correct things in my cut-down ‘reproducer’ code allowing the datasource to be read. Yet when I took the same change to my ‘production’ code, removing the random function in resource names had no affect. So it definitely seems to be something more related to sequencing and timing and how big the dependency tree is and what order the tree is. i.e Why resource instance state can be found in one flow, but not in the other.
resource "random_id" "rng" {
/*
keepers = {
first = "${timestamp()}"
}
*/
byte_length = 2
}