Terraform 1.4.6 works with my provider, but 1.5.0 does not.
The error is:
│ Error: Provider produced invalid plan
│
│ Provider "registry.terraform.io/juniper/apstra" planned an invalid value for apstra_interface_map.test.interfaces: count in plan
│ (cty.UnknownVal(cty.Number)) disagrees with count in config (cty.NumberIntVal(2)).
│
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.
The attribute in question is a RequiredSetNestedAttribute with an Optional + Computed attribute inside.
I’ve had problems in other cases with complicated SetNestedAttributes, but those tended to revolve around dereferencing set elements with unknown nested element values. Failing to count the set members (I guess that’s what’s happening?) seems new.
Hey @hQnVyLRx Thanks for raising this and sorry you’re running into trouble here. Let’s see if we can figure out what’s going on.
Do you happen to have the associated configuration snippet for this handy? It’d also be helpful to know if the configuration was changed to trigger a create/update plan or if this only happening during a plan that’s expected to cause no changes.
The error diagnostic content/formatting seems to suggest the error is being raised by Terraform core though. That doesn’t always mean it wasn’t because of something on the provider side, but seeing the behavior change only through upgrading the Terraform version seems most suspect. I’m guessing though that maybe there could have been subtle internal changes to the core planning logic between 1.4 and 1.5 since the newer version implemented import logic into the plan graph. I believe 1.5 also introduced some subtle internal type system updates. It may be worth raising an issue in Issues · hashicorp/terraform · GitHub in case one of those maintainers may recognize a recent change that would have potentially caused this.
The error occurs on initial plan generation. No need for any prior state.
You can replicate the behavior with (a) the following config and (b) an immediate return in the provider’s Configure() and the resource’s ValidateConfig() from the provider’s main branch. Without those returns, the provider will bail out too early.
The config required is:
# The bogus URL below only "works" if the following functions are modified to return immediately:
# - Configure() in apstra/Provider.go()
# - ValidateConfig() in apstra/resource_interface_map.go()
provider "apstra" { url = "https://user:pass@0.0.0.0" }
resource "apstra_interface_map" "x" {
name = "x"
logical_device_id = "x"
device_profile_id = "x"
interfaces = [
{ logical_device_port = "1/1", physical_interface_name = "x" },
{ logical_device_port = "1/2", physical_interface_name = "y" },
]
}
I noticed this morning that the error doesn’t occur when only a single interface is supplied in the configuration.
Removing UseStateForUnknown in the nested attribute (two instances of it) doesn’t seem to have made any difference in the few minutes I’ve had to look at it this morning.
I think the problem here is that interfaces is a nested set, but you have an optionally-computed attribute inside that set. Because elements of a set are determined by their entire value, ~if any attribute becomes unknown the entire set therefor becomes unknown~ (EDIT: turns out the framework is not causing this to happen), which is not allowed if there is configuration present for that set.
It basically comes down to optional+computed attributes are not really possible within a set.
Oh yes, it’s really just the computed concept that is a problem here (because really from a plan validation perspective, something is either computed, or it isn’t, the optional aspect is irrelevant). The legacy SDK tried to work around these partial-value-in-set problems with the idea of the custom set hash function, but that doesn’t work because what is treated as a set element must align exactly with how core treats the set.
I’m not certain how this worked for you in v1.4, because the point where this is erroring would have been a crash in prior versions since we never could encounter the situation with the old SDK. With a single element, the set might not be entirely unknown (I can’t recall how precise that evaluation is), since there is no possibility of multiple elements resolving to the same value.
Now that I think about it some more though, perhaps we could make this pass now that we have the more refined structural attribute handling … I need to look into it a little more closely, but it’s possible this validation check could be made to pass with better validation after apply.