Merge pull request #38267 from hashicorp/jbardin/backport-38264

manual v1.14 backport of #38264
pull/38299/head
James Bardin 1 month ago committed by GitHub
commit 36708cedc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
kind: BUG FIXES
body: Prevent crash in the display of relevant attributes after provider upgrades
time: 2026-03-11T16:38:04.50368-04:00
custom:
Issue: "38264"

@ -18,7 +18,7 @@ import (
//
// The caller of the above functions is required to know whether the next value
// in the path is a list type or an object type and call the relevant function,
// otherwise these functions will crash/panic.
// otherwise no match will be returned.
//
// The Matches function returns true if the paths you have traversed until now
// ends.
@ -151,8 +151,18 @@ func (p *PathMatcher) GetChildWithKey(key string) Matcher {
continue
}
if path[0].(string) == key {
child.Paths = append(child.Paths, path[1:])
switch val := path[0].(type) {
case string:
if val == key {
child.Paths = append(child.Paths, path[1:])
}
case float64:
// here we must assume the path being looked up no longer matches
// the given data structure, so the caller in incorrect. This is
// fine, because it only means that we don't match any paths.
default:
panic(fmt.Errorf("found invalid type within path (%v:%T), the validation shouldn't have allowed this to happen; this is a bug in Terraform, please report it", val, val))
}
}
return child
@ -190,15 +200,12 @@ func (p *PathMatcher) GetChildWithIndex(index int) Matcher {
switch val := path[0].(type) {
case float64:
if int(path[0].(float64)) == index {
if int(val) == index {
child.Paths = append(child.Paths, path[1:])
}
case string:
f, err := strconv.ParseFloat(val, 64)
if err != nil {
panic(fmt.Errorf("found invalid type within path (%v:%T), the validation shouldn't have allowed this to happen; this is a bug in Terraform, please report it", val, val))
}
if int(f) == index {
if err == nil && int(f) == index {
child.Paths = append(child.Paths, path[1:])
}
default:

@ -254,3 +254,39 @@ func TestPathMatcher_MultiplePaths(t *testing.T) {
t.Errorf("should not have partial matched at leaf level")
}
}
// Since paths may be coming from relevant attributes, and those paths may no
// longer correspond to an updated schema, we can't always be certain the caller
// knows the correct type.
func TestPathMatcher_WrongKeyTypes(t *testing.T) {
var matcher Matcher
matcher = &PathMatcher{
Paths: [][]interface{}{
{
float64(0),
"key",
float64(0),
},
},
}
failed := matcher.GetChildWithKey("key")
if failed.Matches() || failed.MatchesPartial() {
t.Errorf("should not have any match at on failure")
}
matcher = matcher.GetChildWithIndex(0).GetChildWithKey("key")
if matcher.Matches() {
t.Errorf("should not have exact matched at first level")
}
if !matcher.MatchesPartial() {
t.Errorf("should have partial matched at first level")
}
failed = matcher.GetChildWithKey("zero")
if failed.Matches() || failed.MatchesPartial() {
t.Errorf("should not have any match at on failure")
}
}

Loading…
Cancel
Save