diff --git a/internal/plans/changes.go b/internal/plans/changes.go index 1ed49724b055..662a28a04dc7 100644 --- a/internal/plans/changes.go +++ b/internal/plans/changes.go @@ -40,12 +40,14 @@ func NewChanges() *Changes { // Encode encodes all the stored resource and output changes into a new *ChangeSrc value func (c *Changes) Encode(schemas *schemarepo.Schemas) (*ChangesSrc, error) { + // a plan is always built even when there are errors, so make sure to return + // a valid changesSrc. changesSrc := NewChangesSrc() for _, rc := range c.Resources { p, ok := schemas.Providers[rc.ProviderAddr.Provider] if !ok { - return nil, fmt.Errorf("Changes.Encode: missing provider %s for %s", rc.ProviderAddr, rc.Addr) + return changesSrc, fmt.Errorf("Changes.Encode: missing provider %s for %s", rc.ProviderAddr, rc.Addr) } var schema providers.Schema @@ -59,12 +61,12 @@ func (c *Changes) Encode(schemas *schemarepo.Schemas) (*ChangesSrc, error) { } if schema.Block == nil { - return nil, fmt.Errorf("Changes.Encode: missing schema for %s", rc.Addr) + return changesSrc, fmt.Errorf("Changes.Encode: missing schema for %s", rc.Addr) } rcs, err := rc.Encode(schema.Block.ImpliedType()) if err != nil { - return nil, fmt.Errorf("Changes.Encode: %w", err) + return changesSrc, fmt.Errorf("Changes.Encode: %w", err) } changesSrc.Resources = append(changesSrc.Resources, rcs) @@ -73,7 +75,7 @@ func (c *Changes) Encode(schemas *schemarepo.Schemas) (*ChangesSrc, error) { for _, ocs := range c.Outputs { oc, err := ocs.Encode() if err != nil { - return nil, err + return changesSrc, err } changesSrc.Outputs = append(changesSrc.Outputs, oc) } diff --git a/internal/plans/changes_test.go b/internal/plans/changes_test.go index 51faa0828ea2..e400d4064a28 100644 --- a/internal/plans/changes_test.go +++ b/internal/plans/changes_test.go @@ -43,3 +43,27 @@ func TestChangeEncodeSensitive(t *testing.T) { }) } } + +// make sure we get a valid value back even when faced with an error +func TestChangeEncodeError(t *testing.T) { + changes := &Changes{ + Outputs: []*OutputChange{ + { + // Missing Addr + Change: Change{ + Before: cty.NullVal(cty.DynamicPseudoType), + // can't encode a marked value + After: cty.StringVal("test").Mark("shoult not be here"), + }, + }, + }, + } + // no resources so we can get by with no schemas + changesSrc, err := changes.Encode(nil) + if err == nil { + t.Fatal("expected error") + } + if changesSrc == nil { + t.Fatal("changesSrc should not be nil") + } +}