-
Notifications
You must be signed in to change notification settings - Fork 9.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
deprecation warning for destroy provisioner refs #23559
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,11 @@ func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) { | |
} | ||
} | ||
|
||
// destroy provisioners can only refer to self | ||
if pv.When == ProvisionerWhenDestroy { | ||
diags = append(diags, onlySelfRefs(config)...) | ||
} | ||
|
||
if attr, exists := content.Attributes["on_failure"]; exists { | ||
expr, shimDiags := shimTraversalInString(attr.Expr, true) | ||
diags = append(diags, shimDiags...) | ||
|
@@ -85,8 +90,11 @@ func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) { | |
} | ||
seenConnection = block | ||
|
||
//conn, connDiags := decodeConnectionBlock(block) | ||
//diags = append(diags, connDiags...) | ||
// destroy provisioners can only refer to self | ||
if pv.When == ProvisionerWhenDestroy { | ||
diags = append(diags, onlySelfRefs(block.Body)...) | ||
} | ||
|
||
pv.Connection = &Connection{ | ||
Config: block.Body, | ||
DeclRange: block.DefRange, | ||
|
@@ -107,6 +115,49 @@ func decodeProvisionerBlock(block *hcl.Block) (*Provisioner, hcl.Diagnostics) { | |
return pv, diags | ||
} | ||
|
||
func onlySelfRefs(body hcl.Body) hcl.Diagnostics { | ||
var diags hcl.Diagnostics | ||
|
||
// Provisioners currently do not use any blocks in their configuration. | ||
// Blocks are likely to remain solely for meta parameters, but in the case | ||
// that blocks are supported for provisioners, we will want to extend this | ||
// to find variables in nested blocks. | ||
attrs, _ := body.JustAttributes() | ||
for _, attr := range attrs { | ||
for _, v := range attr.Expr.Variables() { | ||
valid := false | ||
switch v.RootName() { | ||
case "self": | ||
valid = true | ||
case "count": | ||
// count must use "index" | ||
if len(v) == 2 { | ||
if t, ok := v[1].(hcl.TraverseAttr); ok && t.Name == "index" { | ||
valid = true | ||
} | ||
} | ||
|
||
case "each": | ||
if len(v) == 2 { | ||
if t, ok := v[1].(hcl.TraverseAttr); ok && t.Name == "key" { | ||
valid = true | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't there be a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any names not marked as As for a default case, any possible identifier is valid in other contexts, but we want to limit the destroy provisioners to only these 3 cases. I didn't use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops! Thank you for the explanation. |
||
|
||
if !valid { | ||
diags = append(diags, &hcl.Diagnostic{ | ||
Severity: hcl.DiagWarning, | ||
Summary: "External references from destroy provisioners are deprecated", | ||
Detail: "Destroy time provisioners and their connections may only reference values stored in the instance state, which include 'self', 'count.index', or 'each.key'.", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be handy to also include what they had used/referenced? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That will be automatically generated by the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a subjective thing and I won't mind at all if others disagree, but I think I'd lean towards making this error message a little less implementation-details-y by not mentioning the "instance state" at all. For example:
For our other deprecation warnings in this cycle we've included an extra paragraph giving a bit of a "why". This one is too hairy to go into all the details, but perhaps as a compromise we could add an additional sentence something like this:
As a bonus, a sentence like that might help a user connect the dots between this warning and a subsequent error reporting a graph cycle, giving them a better clue as to how to resolve that error. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another idea, though this one is definitely in the "optional polish" category: Could we perhaps recognize the situation where the problem is in a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do like that wording better, I'll push an update to that tomorrow. As for the separate connection blocks, you're right it's a bit hairy because they're loaded separately. Following the path of making config more explicit and easier to understand, I don't think this imposes large burden to move a resource connection into the compatible provisioner when it's encountered, and then the logic of overriding doesn't have to be taken into account be the loader or the user. |
||
Subject: attr.Expr.Range().Ptr(), | ||
}) | ||
} | ||
} | ||
} | ||
return diags | ||
} | ||
|
||
// Connection represents a "connection" block when used within either a | ||
// "resource" or "provisioner" block in a module or file. | ||
type Connection struct { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
locals { | ||
user = "name" | ||
} | ||
|
||
resource "null_resource" "a" { | ||
connection { | ||
host = self.hostname | ||
user = local.user # WARNING: External references from destroy provisioners are deprecated | ||
} | ||
|
||
provisioner "remote-exec" { | ||
when = destroy | ||
index = count.index | ||
key = each.key | ||
|
||
} | ||
} | ||
|
||
resource "null_resource" "b" { | ||
connection { | ||
host = self.hostname | ||
# this is OK since there is no destroy provisioner | ||
user = local.user | ||
} | ||
|
||
provisioner "remote-exec" { | ||
} | ||
} | ||
|
||
resource "null_resource" "b" { | ||
provisioner "remote-exec" { | ||
when = destroy | ||
connection { | ||
host = self.hostname | ||
user = local.user # WARNING: External references from destroy provisioners are deprecated | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yay comments! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I missed this feature last time around, but it's a really nice test fixture from @apparentlymart! |
||
} | ||
|
||
command = "echo ${local.name}" # WARNING: External references from destroy provisioners are deprecated | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tiny nitpick/question: since we're only giving warnings right now should this comment say
destroy provisioners _should_ only refer to self
?I am completely ok with disagreement :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though that was only there because I backported this from it being an error, I think it might be better as "can". In this case, they "can only refer to self" in order to avoid the deprecation warnings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice clarification, makes sense to me (and I wasn't going to fight you on it anyway)!