@@ -39,11 +39,11 @@ func AssertPlanValid(schema *configschema.Block, priorState, config, plannedStat
3939func assertPlanValid (schema * configschema.Block , priorState , config , plannedState cty.Value , path cty.Path ) []error {
4040 var errs []error
4141 if plannedState .IsNull () && ! config .IsNull () {
42- errs = append (errs , path .NewErrorf ("planned for absense but config wants existence" ))
42+ errs = append (errs , path .NewErrorf ("planned for absence but config wants existence" ))
4343 return errs
4444 }
4545 if config .IsNull () && ! plannedState .IsNull () {
46- errs = append (errs , path .NewErrorf ("planned for existence but config wants absense " ))
46+ errs = append (errs , path .NewErrorf ("planned for existence but config wants absence " ))
4747 return errs
4848 }
4949 if plannedState .IsNull () {
@@ -286,6 +286,11 @@ func assertPlannedValueValid(attrS *configschema.Attribute, priorV, configV, pla
286286 }
287287 return errs
288288 }
289+ } else {
290+ if attrS .Computed {
291+ errs = append (errs , path .NewErrorf ("configuration present for computed attribute" ))
292+ return errs
293+ }
289294 }
290295
291296 // If this attribute has a NestedType, validate the nested object
@@ -317,11 +322,11 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
317322 var errs []error
318323
319324 if planned .IsNull () && ! config .IsNull () {
320- errs = append (errs , path .NewErrorf ("planned for absense but config wants existence" ))
325+ errs = append (errs , path .NewErrorf ("planned for absence but config wants existence" ))
321326 return errs
322327 }
323328 if config .IsNull () && ! planned .IsNull () {
324- errs = append (errs , path .NewErrorf ("planned for existence but config wants absense " ))
329+ errs = append (errs , path .NewErrorf ("planned for existence but config wants absence " ))
325330 return errs
326331 }
327332 if planned .IsNull () {
@@ -349,10 +354,6 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
349354 for it := planned .ElementIterator (); it .Next (); {
350355 idx , plannedEV := it .Element ()
351356 path := append (path , cty.IndexStep {Key : idx })
352- if ! plannedEV .IsKnown () {
353- errs = append (errs , path .NewErrorf ("element representing nested block must not be unknown itself; set nested attribute values to unknown instead" ))
354- continue
355- }
356357 if ! config .HasIndex (idx ).True () {
357358 continue // should never happen since we checked the lengths above
358359 }
@@ -387,16 +388,11 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
387388 for k , plannedEV := range plannedVals {
388389 configEV , ok := configVals [k ]
389390 if ! ok {
390- errs = append (errs , path .NewErrorf ("block key %q from plan is not present in config" , k ))
391+ errs = append (errs , path .NewErrorf ("map key %q from plan is not present in config" , k ))
391392 continue
392393 }
393394 path := append (path , cty.GetAttrStep {Name : k })
394395
395- if ! plannedEV .IsKnown () {
396- errs = append (errs , path .NewErrorf ("element representing nested block must not be unknown itself; set nested attribute values to unknown instead" ))
397- continue
398- }
399-
400396 priorEV , ok := priorVals [k ]
401397 if ! ok {
402398 priorEV = cty .NullVal (schema .ImpliedType ())
@@ -406,31 +402,22 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
406402 }
407403 for k := range configVals {
408404 if _ , ok := plannedVals [k ]; ! ok {
409- errs = append (errs , path .NewErrorf ("block key %q from config is not present in plan" , k ))
405+ errs = append (errs , path .NewErrorf ("map key %q from config is not present in plan" , k ))
410406 continue
411407 }
412408 }
413409
414410 case configschema .NestingSet :
411+ plannedL := planned .LengthInt ()
412+ configL := config .LengthInt ()
413+ if plannedL != configL {
414+ errs = append (errs , path .NewErrorf ("count in plan (%d) disagrees with count in config (%d)" , plannedL , configL ))
415+ return errs
416+ }
415417 // Because set elements have no identifier with which to correlate
416- // them, we can't robustly validate the plan for a nested block
418+ // them, we can't robustly validate the plan for a nested object
417419 // backed by a set, and so unfortunately we need to just trust the
418- // provider to do the right thing. :(
419- //
420- // (In principle we could correlate elements by matching the
421- // subset of attributes explicitly set in config, except for the
422- // special diff suppression rule which allows for there to be a
423- // planned value that is constructed by mixing part of a prior
424- // value with part of a config value, creating an entirely new
425- // element that is not present in either prior nor config.)
426- for it := planned .ElementIterator (); it .Next (); {
427- idx , plannedEV := it .Element ()
428- path := append (path , cty.IndexStep {Key : idx })
429- if ! plannedEV .IsKnown () {
430- errs = append (errs , path .NewErrorf ("element representing nested block must not be unknown itself; set nested attribute values to unknown instead" ))
431- continue
432- }
433- }
420+ // provider to do the right thing.
434421 }
435422
436423 return errs
0 commit comments