-
Notifications
You must be signed in to change notification settings - Fork 44
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
Refer to Terraform diff to generate a more precise diff #1499
Conversation
Add resulting diff information to Pulumi diff
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.
This will need to be under test to merge. To start, I would write table-driven unit tests for parseTFPath
. You can use shim/schema.*
to mock shim.Schema*
interfaces:
pulumi-terraform-bridge/pkg/tfshim/schema/schema.go
Lines 140 to 142 in b83370c
//nolint:revive | |
type SchemaMap map[string]shim.Schema | |
} | ||
// reset the schema map to point at the nested schema | ||
if nestedSchema != nil { | ||
if res, isres := nestedSchema.Elem().(shim.Resource); isres { |
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.
If !isres
, then tfs
should be set to nil
. A misalignment doesn't mean that no traversal happened.
Also, it's not actually a resource:
if res, isres := nestedSchema.Elem().(shim.Resource); isres { | |
if res, isObj := nestedSchema.Elem().(shim.Resource); isObj { |
nestedSchema, found := tfs.GetOk(field) | ||
if found { |
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.
Tightening the scoping makes it harder to misuse these variables.
nestedSchema, found := tfs.GetOk(field) | |
if found { | |
if nestedSchema, found := tfs.GetOk(field); found { |
} else { | ||
// check if the field is a number | ||
// the error value for strconv.Atoi is 0, so we look at the error. | ||
_, err := strconv.Atoi(field) // the error value here is 0, so we look at the error. | ||
if err == nil { | ||
// we found an index | ||
pulumiPath = pulumiPath + "[" + field + "]" | ||
} else { | ||
// Ignore special characters from Terraform |
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.
I think this would read clearer if we reduce the nesting.
} else { | |
// check if the field is a number | |
// the error value for strconv.Atoi is 0, so we look at the error. | |
_, err := strconv.Atoi(field) // the error value here is 0, so we look at the error. | |
if err == nil { | |
// we found an index | |
pulumiPath = pulumiPath + "[" + field + "]" | |
} else { | |
// Ignore special characters from Terraform | |
continue | |
} | |
// check if the field is a number | |
// the error value for strconv.Atoi is 0, so we look at the error. | |
_, err := strconv.Atoi(field) // the error value here is 0, so we look at the error. | |
if err == nil { | |
// we found an index | |
pulumiPath = pulumiPath + "[" + field + "]" | |
continue | |
} | |
// Ignore special characters from Terraform |
// TODO: Using PropertyDiff_ADD is not entirely accurate in every case. | ||
// TODO: (cont) We may want to pass on a more generic UPDATE strategy here - less precise, less error prone. |
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.
Can you give an example for the case there PropertyDiff_ADD
is the wrong case? What is the effect of getting the kind wrong (is it just display)?
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.
It could be a PropertyDiff_UPDATE, on an already-existing object key.
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.
Thank you for looking into this!
Making changes to this code is currently an extremely high-risk area, and existing coverage is very inadequate to verify changes. If you're contributing to the expectation is to have 100% coverage on changes but also back-filling missing coverage.
While it is possible to continue with the chosen approach and get there, it is going to be require some work.
Can we discuss alternative approaches that avoid high-risk edits? Perhaps we can start with a repro of the original problem?
changes := pulumirpc.DiffResponse_DIFF_NONE | ||
if len(diff) > 0 || *forceDiff { | ||
changes = pulumirpc.DiffResponse_DIFF_SOME | ||
} | ||
return diff, changes | ||
} | ||
|
||
func parseTFPath(path string, tfs shim.SchemaMap, ps map[string]*SchemaInfo) (string, bool) { |
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.
Do we understand the semantics of paths here, both the TF paths and Pulumi paths?
What happens with set elements? (represented as hashes in TF paths). Should these be mapped to Pulumi numbers as steps are represented as lists?
What happens with flattening (when Pulumi paths are shorter than TF paths with MaxItems=1).
diff[pulumiPath] = &pulumirpc.PropertyDiff{Kind: pulumirpc.PropertyDiff_UPDATE} | ||
} | ||
} | ||
} | ||
changes := pulumirpc.DiffResponse_DIFF_NONE |
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.
What would happen if we considered changing the changes
only without populating diff[pulumiPath]
at all? Is there a way such an approach could get us to passing the bug, possibly with incorrect detailed diff displayed to the user?
Linking related issue #1498 |
@@ -309,9 +309,71 @@ func makeDetailedDiff( | |||
makePropertyDiff(ctx, en, string(k), v, tfDiff, diff, forceDiff, etf, eps, true, useRawNames(etf)) | |||
} | |||
|
|||
// In some cases, the terraform diff will have additional attributes not covered by Pulumi's olds and news. |
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.
For my education can you spell it out as a full example for the GCP problem. I understand this is related to GCP provider-level labels, what's the attribute name and is it possible to show a printout of tfDiff in question. Much appreciated.
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.
Here is a tfDiff.Attributes() when adding the new GCP labels:
"effective_labels.%": {
Old: "3",
New: "4",
NewComputed: false,
NewRemoved: false,
NewExtra: nil,
RequiresNew: false,
Sensitive: false,
Type: 0x0,
},
"effective_labels.new": {
Old: "",
New: "defaultLabel",
NewComputed: false,
NewRemoved: false,
NewExtra: nil,
RequiresNew: false,
Sensitive: false,
Type: 0x0,
},
"terraform_labels.%": {
Old: "3",
New: "4",
NewComputed: false,
NewRemoved: false,
NewExtra: nil,
RequiresNew: false,
Sensitive: false,
Type: 0x0,
},
"terraform_labels.new": {
Old: "",
New: "defaultLabel",
NewComputed: false,
NewRemoved: false,
NewExtra: nil,
RequiresNew: false,
Sensitive: false,
Type: 0x0,
},
}
Should we close this given that we merged #1502? |
I have filed #1504 detailing remaining work to consider here, and why we should consider finishing this up. I will close for now. I think there's a substantial amount of work required to get this right; the code in this PR will still be linked to 1504 if we need to find it again. |
This pull request looks at the Terraform Diff Attributes, checks if they exist in the Pulumi diff generated by
olds
andnews
, and adds any additional diff information to Pulumi diff.Points of concern:
Addresses #1491.