create index-able types for validation
Since objects and tuples have fixed numbers of elements, we can't return an unknown version of those during validation. While we could return a DyanmicVal (which was used previously), that prevents the validation of outputs and attributes in config references. Instead, we can return a synthetic type made from a List or Map based on the configuration, which will allow us to more precisely validate indexes, attributes, and outputs.
This commit is contained in:
parent
91e243b878
commit
7e6d07ee46
|
@ -399,9 +399,15 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc
|
||||||
// module instance.
|
// module instance.
|
||||||
moduleInstances := map[addrs.InstanceKey]map[string]cty.Value{}
|
moduleInstances := map[addrs.InstanceKey]map[string]cty.Value{}
|
||||||
|
|
||||||
|
// create a dummy object type for validation below
|
||||||
|
unknownMap := map[string]cty.Type{}
|
||||||
|
|
||||||
// the structure is based on the configuration, so iterate through all the
|
// the structure is based on the configuration, so iterate through all the
|
||||||
// defined outputs, and add any instance state or changes we find.
|
// defined outputs, and add any instance state or changes we find.
|
||||||
for _, cfg := range outputConfigs {
|
for _, cfg := range outputConfigs {
|
||||||
|
// record the output names for validation
|
||||||
|
unknownMap[cfg.Name] = cty.DynamicPseudoType
|
||||||
|
|
||||||
// get all instance output for this path from the state
|
// get all instance output for this path from the state
|
||||||
for key, states := range stateMap {
|
for key, states := range stateMap {
|
||||||
outputState, ok := states[cfg.Name]
|
outputState, ok := states[cfg.Name]
|
||||||
|
@ -521,10 +527,22 @@ func (d *evaluationStateData) GetModule(addr addrs.ModuleCall, rng tfdiags.Sourc
|
||||||
// the objects based on the configuration.
|
// the objects based on the configuration.
|
||||||
if d.Operation == walkValidate {
|
if d.Operation == walkValidate {
|
||||||
// While we know the type here and it would be nice to validate whether
|
// While we know the type here and it would be nice to validate whether
|
||||||
// indexes are valid or not, because tuples have a fixed number of
|
// indexes are valid or not, because tuples and objects have fixed
|
||||||
// elements we can't simply return an unknown tuple type since we have
|
// numbers of elements we can't simply return an unknown value of the
|
||||||
// not expanded any instances during validation.
|
// same type since we have not expanded any instances during
|
||||||
return cty.DynamicVal, diags
|
// validation.
|
||||||
|
//
|
||||||
|
// In order to validate the expression a little precisely, we'll create
|
||||||
|
// an unknown map or list here to get more type information.
|
||||||
|
ty := cty.Object(unknownMap)
|
||||||
|
switch {
|
||||||
|
case callConfig.Count != nil:
|
||||||
|
ret = cty.UnknownVal(cty.List(ty))
|
||||||
|
case callConfig.ForEach != nil:
|
||||||
|
ret = cty.UnknownVal(cty.Map(ty))
|
||||||
|
default:
|
||||||
|
ret = cty.UnknownVal(ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, diags
|
return ret, diags
|
||||||
|
@ -759,10 +777,21 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc
|
||||||
// unknown.
|
// unknown.
|
||||||
if d.Operation == walkValidate {
|
if d.Operation == walkValidate {
|
||||||
// While we know the type here and it would be nice to validate whether
|
// While we know the type here and it would be nice to validate whether
|
||||||
// indexes are valid or not, because tuples have a fixed number of
|
// indexes are valid or not, because tuples and objects have fixed
|
||||||
// elements we can't simply return an unknown tuple type since we have
|
// numbers of elements we can't simply return an unknown value of the
|
||||||
// not expanded any instances during validation.
|
// same type since we have not expanded any instances during
|
||||||
return cty.DynamicVal, diags
|
// validation.
|
||||||
|
//
|
||||||
|
// In order to validate the expression a little precisely, we'll create
|
||||||
|
// an unknown map or list here to get more type information.
|
||||||
|
switch {
|
||||||
|
case config.Count != nil:
|
||||||
|
ret = cty.UnknownVal(cty.List(ty))
|
||||||
|
case config.ForEach != nil:
|
||||||
|
ret = cty.UnknownVal(cty.Map(ty))
|
||||||
|
default:
|
||||||
|
ret = cty.UnknownVal(ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, diags
|
return ret, diags
|
||||||
|
|
Loading…
Reference in New Issue