Open adi-garg opened 1 year ago
Thanks for sharing this, @adi-garg.
I think the subtlety that this documentation isn't currently considering is that there's a difference between a resource (the resource
block) and a resource instance, which we use to describe the effect of using count
and for_each
in a resource
block.
For a resource that doesn't use count
or for_each
, self
is exactly equivalent to referring to the one and only instance of that resource, because in that case the resource address and the resource instance address are identical.
When a resource uses count
or for_each
the situation is different, because self
in that case refers to the current instance that is being provisioned. For example:
resource "example" "example" {
count = 2
connection {
host = self.public_ip
# ...
}
}
In the above, the connection
block will be evaluated twice. Each time self
will be an alias for a different object: example.example[0]
or example.example[1]
. In this case it would not be valid to refer to example.example
as a whole because that would create a dependency cycle, but it's valid to refer to self
because Terraform knows for certain that it's a reference only to the current instance and that connection
blocks always get evaluated only as part of applying that instance.
Internally Terraform treats self
as literally a shorthand for some specific object in scope, so if it's valid to refer to self
then it's also always valid to refer to exactly what self
expands to. In the case of a single-instance resource self
expands to the resource itself because that is synonymous with the resource's single instance, but for a multi-instance resource self
expands to a reference to a particular instance and so referring to the resource as a whole is not valid.
There are some other subtleties here with how Terraform treats a constant instance key like example.example[0]
differently than a dynamically-chosen one like example.example[count.index]
, but I think those details are not super important and it's better to focus on describing what self
expands to in each case.
Thanks again for reporting this!
Terraform Version
Affected Pages
1.https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax#the-self-object 2.https://developer.hashicorp.com/terraform/language/resources/provisioners/connection
What is the docs issue?
1.SELF-OBJECT: The lines: _Expressions in provisioner blocks cannot refer to their parent resource by name. Instead, they can use the special self object. The self object represents the provisioner's parent resource, and has all of that resource's attributes. For example, use self.public_ip to reference an aws_instance's publicip attribute.
AND Technical note: Resource references are restricted here because references create dependencies. Referring to a resource by name within its own block would create a dependency cycle.
seem to indicate that it is not possible to use something like
command = "echo ${aws_instance.myec2.private_ip} >> private_ips.txt"
inside provisioner block with references to own resource. 'self' object is suggested instead.
Infact,the below code works:
The documentation in turn also makes such references as seen here.
"consul join ${aws_instance.web.private_ip}",
2.CONNECTION DOCUMENT:
Again, the following lines may be flawed-
The below code works well while using a reference to own parent using name: connection { type = "ssh" user = "ec2-user" private_key = file("./tf-key.pem")
host = self.public_ip
host = aws_instance.myec2.public_ip }
Proposal
Modification to both documents needed based on clarification.
+It may be noted that 'self' object explanation works as an alternative(perhaps this usage can be talked about in the document for provisioners):
command = "echo ${aws_instance.myec2.private_ip} >> private_ips.txt"
CAN BE RE-WRITTEN AS (referencing above code snippet) /using 'self' object:
command = "echo ${self.private_ip} >> private_ips.txt "
Similarly, both the below syntaxes under ‘connection’ block(used with ‘remote-exec’ provisioners) are valid:
+It may also help to emphasize that self-object can be used with both local-exec and remote-exec provisioners.
References
No response