helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
package schema
|
|
|
|
|
|
|
|
import (
|
2017-05-31 06:34:02 +02:00
|
|
|
"errors"
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
2017-05-25 18:31:31 +02:00
|
|
|
"sync"
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/terraform"
|
|
|
|
)
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// newValueWriter is a minor re-implementation of MapFieldWriter to include
|
|
|
|
// keys that should be marked as computed, to represent the new part of a
|
|
|
|
// pseudo-diff.
|
|
|
|
type newValueWriter struct {
|
|
|
|
*MapFieldWriter
|
|
|
|
|
|
|
|
// A list of keys that should be marked as computed.
|
|
|
|
computedKeys map[string]bool
|
|
|
|
|
|
|
|
// A lock to prevent races on writes. The underlying writer will have one as
|
|
|
|
// well - this is for computed keys.
|
|
|
|
lock sync.Mutex
|
2017-05-31 19:02:25 +02:00
|
|
|
|
|
|
|
// To be used with init.
|
|
|
|
once sync.Once
|
|
|
|
}
|
|
|
|
|
|
|
|
// init performs any initialization tasks for the newValueWriter.
|
|
|
|
func (w *newValueWriter) init() {
|
|
|
|
if w.computedKeys == nil {
|
|
|
|
w.computedKeys = make(map[string]bool)
|
|
|
|
}
|
2017-05-25 18:31:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// WriteField overrides MapValueWriter's WriteField, adding the ability to flag
|
|
|
|
// the address as computed.
|
|
|
|
func (w *newValueWriter) WriteField(address []string, value interface{}, computed bool) error {
|
2017-05-31 06:34:02 +02:00
|
|
|
// Fail the write if we have a non-nil value and computed is true.
|
|
|
|
// NewComputed values should not have a value when written.
|
|
|
|
if value != nil && computed {
|
|
|
|
return errors.New("Non-nil value with computed set")
|
|
|
|
}
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
if err := w.MapFieldWriter.WriteField(address, value); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-05-31 19:02:25 +02:00
|
|
|
w.once.Do(w.init)
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
w.lock.Lock()
|
|
|
|
defer w.lock.Unlock()
|
|
|
|
if computed {
|
|
|
|
w.computedKeys[strings.Join(address, ".")] = true
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ComputedKeysMap returns the underlying computed keys map.
|
|
|
|
func (w *newValueWriter) ComputedKeysMap() map[string]bool {
|
2017-05-31 19:02:25 +02:00
|
|
|
w.once.Do(w.init)
|
2017-05-25 18:31:31 +02:00
|
|
|
return w.computedKeys
|
|
|
|
}
|
|
|
|
|
|
|
|
// newValueReader is a minor re-implementation of MapFieldReader and is the
|
|
|
|
// read counterpart to MapValueWriter, allowing the read of keys flagged as
|
|
|
|
// computed to accommodate the diff override logic in ResourceDiff.
|
|
|
|
type newValueReader struct {
|
|
|
|
*MapFieldReader
|
|
|
|
|
|
|
|
// The list of computed keys from a newValueWriter.
|
|
|
|
computedKeys map[string]bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadField reads the values from the underlying writer, returning the
|
|
|
|
// computed value if it is found as well.
|
|
|
|
func (r *newValueReader) ReadField(address []string) (FieldReadResult, error) {
|
2017-05-28 03:17:41 +02:00
|
|
|
addrKey := strings.Join(address, ".")
|
2017-05-25 18:31:31 +02:00
|
|
|
v, err := r.MapFieldReader.ReadField(address)
|
|
|
|
if err != nil {
|
|
|
|
return FieldReadResult{}, err
|
|
|
|
}
|
2017-05-28 03:17:41 +02:00
|
|
|
for computedKey := range r.computedKeys {
|
2017-05-31 18:51:00 +02:00
|
|
|
if childAddrOf(addrKey, computedKey) {
|
2017-05-28 03:17:41 +02:00
|
|
|
if strings.HasSuffix(addrKey, ".#") {
|
|
|
|
// This is a count value for a list or set that has been marked as
|
|
|
|
// computed, or a sub-list/sub-set of a complex resource that has
|
|
|
|
// been marked as computed. We need to pass through to other readers
|
|
|
|
// so that an accurate previous count can be fetched for the diff.
|
|
|
|
v.Exists = false
|
|
|
|
}
|
|
|
|
v.Computed = true
|
|
|
|
}
|
2017-05-25 18:31:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return v, nil
|
|
|
|
}
|
|
|
|
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
// ResourceDiff is used to query and make custom changes to an in-flight diff.
|
|
|
|
// It can be used to veto particular changes in the diff, customize the diff
|
|
|
|
// that has been created, or diff values not controlled by config.
|
|
|
|
//
|
|
|
|
// The object functions similar to ResourceData, however most notably lacks
|
2017-05-25 18:31:31 +02:00
|
|
|
// Set, SetPartial, and Partial, as it should be used to change diff values
|
2017-05-31 06:45:18 +02:00
|
|
|
// only. Most other first-class ResourceData functions exist, namely Get,
|
2017-05-25 18:31:31 +02:00
|
|
|
// GetOk, HasChange, and GetChange exist.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
//
|
|
|
|
// All functions in ResourceDiff, save for ForceNew, can only be used on
|
|
|
|
// computed fields.
|
|
|
|
type ResourceDiff struct {
|
2017-05-25 18:31:31 +02:00
|
|
|
// The schema for the resource being worked on.
|
|
|
|
schema map[string]*Schema
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// The current config for this resource.
|
|
|
|
config *terraform.ResourceConfig
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// The state for this resource as it exists post-refresh, after the initial
|
|
|
|
// diff.
|
|
|
|
state *terraform.InstanceState
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// The diff created by Terraform. This diff is used, along with state,
|
|
|
|
// config, and custom-set diff data, to provide a multi-level reader
|
|
|
|
// experience similar to ResourceData.
|
|
|
|
diff *terraform.InstanceDiff
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// The internal reader structure that contains the state, config, the default
|
|
|
|
// diff, and the new diff.
|
|
|
|
multiReader *MultiLevelFieldReader
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// A writer that writes overridden new fields.
|
|
|
|
newWriter *newValueWriter
|
2017-05-25 19:03:37 +02:00
|
|
|
|
2017-06-01 18:29:10 +02:00
|
|
|
// Tracks which keys have been updated by ResourceDiff to ensure that the
|
|
|
|
// diff does not get re-run on keys that were not touched, or diffs that were
|
|
|
|
// just removed (re-running on the latter would just roll back the removal).
|
2017-05-25 19:03:37 +02:00
|
|
|
updatedKeys map[string]bool
|
2018-04-07 22:06:47 +02:00
|
|
|
|
|
|
|
// Tracks which keys were flagged as forceNew. These keys are not saved in
|
|
|
|
// newWriter, but we need to track them so that they can be re-diffed later.
|
|
|
|
forcedNewKeys map[string]bool
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// newResourceDiff creates a new ResourceDiff instance.
|
2017-05-25 18:31:31 +02:00
|
|
|
func newResourceDiff(schema map[string]*Schema, config *terraform.ResourceConfig, state *terraform.InstanceState, diff *terraform.InstanceDiff) *ResourceDiff {
|
|
|
|
d := &ResourceDiff{
|
|
|
|
config: config,
|
|
|
|
state: state,
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
diff: diff,
|
2017-05-28 03:17:41 +02:00
|
|
|
schema: schema,
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
d.newWriter = &newValueWriter{
|
|
|
|
MapFieldWriter: &MapFieldWriter{Schema: d.schema},
|
|
|
|
}
|
|
|
|
readers := make(map[string]FieldReader)
|
|
|
|
var stateAttributes map[string]string
|
|
|
|
if d.state != nil {
|
|
|
|
stateAttributes = d.state.Attributes
|
|
|
|
readers["state"] = &MapFieldReader{
|
|
|
|
Schema: d.schema,
|
|
|
|
Map: BasicMapReader(stateAttributes),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if d.config != nil {
|
|
|
|
readers["config"] = &ConfigFieldReader{
|
|
|
|
Schema: d.schema,
|
|
|
|
Config: d.config,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if d.diff != nil {
|
|
|
|
readers["diff"] = &DiffFieldReader{
|
|
|
|
Schema: d.schema,
|
|
|
|
Diff: d.diff,
|
|
|
|
Source: &MultiLevelFieldReader{
|
|
|
|
Levels: []string{"state", "config"},
|
|
|
|
Readers: readers,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2017-05-31 17:03:29 +02:00
|
|
|
readers["newDiff"] = &newValueReader{
|
2017-05-25 18:31:31 +02:00
|
|
|
MapFieldReader: &MapFieldReader{
|
|
|
|
Schema: d.schema,
|
|
|
|
Map: BasicMapReader(d.newWriter.Map()),
|
|
|
|
},
|
|
|
|
computedKeys: d.newWriter.ComputedKeysMap(),
|
|
|
|
}
|
|
|
|
d.multiReader = &MultiLevelFieldReader{
|
|
|
|
Levels: []string{
|
|
|
|
"state",
|
|
|
|
"config",
|
|
|
|
"diff",
|
2017-05-31 17:03:29 +02:00
|
|
|
"newDiff",
|
2017-05-25 18:31:31 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
Readers: readers,
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
2017-05-25 19:03:37 +02:00
|
|
|
d.updatedKeys = make(map[string]bool)
|
2018-04-07 22:06:47 +02:00
|
|
|
d.forcedNewKeys = make(map[string]bool)
|
2017-05-25 19:03:37 +02:00
|
|
|
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
return d
|
|
|
|
}
|
|
|
|
|
2017-06-01 18:29:10 +02:00
|
|
|
// UpdatedKeys returns the keys that were updated by this ResourceDiff run.
|
|
|
|
// These are the only keys that a diff should be re-calculated for.
|
2018-04-07 22:06:47 +02:00
|
|
|
//
|
|
|
|
// This is the combined result of both keys for which diff values were updated
|
|
|
|
// for or cleared, and also keys that were flagged to be re-diffed as a result
|
|
|
|
// of ForceNew.
|
2017-05-25 19:03:37 +02:00
|
|
|
func (d *ResourceDiff) UpdatedKeys() []string {
|
2017-05-31 18:35:53 +02:00
|
|
|
var s []string
|
2017-05-25 19:03:37 +02:00
|
|
|
for k := range d.updatedKeys {
|
|
|
|
s = append(s, k)
|
|
|
|
}
|
2018-04-07 22:06:47 +02:00
|
|
|
for k := range d.forcedNewKeys {
|
|
|
|
for _, l := range s {
|
|
|
|
if k == l {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s = append(s, k)
|
|
|
|
}
|
2017-05-25 19:03:37 +02:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2017-06-01 18:29:10 +02:00
|
|
|
// Clear wipes the diff for a particular key. It is called by ResourceDiff's
|
|
|
|
// functionality to remove any possibility of conflicts, but can be called on
|
|
|
|
// its own to just remove a specific key from the diff completely.
|
2017-05-25 18:45:31 +02:00
|
|
|
//
|
2017-05-28 03:17:41 +02:00
|
|
|
// Note that this does not wipe an override. This function is only allowed on
|
|
|
|
// computed keys.
|
2017-05-25 18:45:31 +02:00
|
|
|
func (d *ResourceDiff) Clear(key string) error {
|
2018-09-26 21:38:38 +02:00
|
|
|
if err := d.checkKey(key, "Clear", true); err != nil {
|
2017-06-01 18:19:03 +02:00
|
|
|
return err
|
2017-05-28 03:17:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return d.clear(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *ResourceDiff) clear(key string) error {
|
2017-05-25 18:45:31 +02:00
|
|
|
// Check the schema to make sure that this key exists first.
|
2018-02-28 13:55:14 +01:00
|
|
|
schemaL := addrToSchema(strings.Split(key, "."), d.schema)
|
|
|
|
if len(schemaL) == 0 {
|
2017-05-25 18:45:31 +02:00
|
|
|
return fmt.Errorf("%s is not a valid key", key)
|
|
|
|
}
|
2018-02-28 13:55:14 +01:00
|
|
|
|
2017-05-25 18:45:31 +02:00
|
|
|
for k := range d.diff.Attributes {
|
|
|
|
if strings.HasPrefix(k, key) {
|
|
|
|
delete(d.diff.Attributes, k)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-02-28 13:55:14 +01:00
|
|
|
// GetChangedKeysPrefix helps to implement Resource.CustomizeDiff
|
|
|
|
// where we need to act on all nested fields
|
|
|
|
// without calling out each one separately
|
|
|
|
func (d *ResourceDiff) GetChangedKeysPrefix(prefix string) []string {
|
|
|
|
keys := make([]string, 0)
|
|
|
|
for k := range d.diff.Attributes {
|
|
|
|
if strings.HasPrefix(k, prefix) {
|
|
|
|
keys = append(keys, k)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return keys
|
|
|
|
}
|
|
|
|
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
// diffChange helps to implement resourceDiffer and derives its change values
|
2017-05-25 18:31:31 +02:00
|
|
|
// from ResourceDiff's own change data, in addition to existing diff, config, and state.
|
2017-12-20 00:46:58 +01:00
|
|
|
func (d *ResourceDiff) diffChange(key string) (interface{}, interface{}, bool, bool, bool) {
|
|
|
|
old, new, customized := d.getChange(key)
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
|
|
|
|
if !old.Exists {
|
|
|
|
old.Value = nil
|
|
|
|
}
|
2018-04-07 22:06:47 +02:00
|
|
|
if !new.Exists || d.removed(key) {
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
new.Value = nil
|
|
|
|
}
|
|
|
|
|
2017-12-20 00:46:58 +01:00
|
|
|
return old.Value, new.Value, !reflect.DeepEqual(old.Value, new.Value), new.Computed, customized
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetNew is used to set a new diff value for the mentioned key. The value must
|
|
|
|
// be correct for the attribute's schema (mostly relevant for maps, lists, and
|
|
|
|
// sets). The original value from the state is used as the old value.
|
|
|
|
//
|
|
|
|
// This function is only allowed on computed attributes.
|
|
|
|
func (d *ResourceDiff) SetNew(key string, value interface{}) error {
|
2018-09-26 21:38:38 +02:00
|
|
|
if err := d.checkKey(key, "SetNew", false); err != nil {
|
2017-06-01 18:19:03 +02:00
|
|
|
return err
|
2017-05-31 17:03:29 +02:00
|
|
|
}
|
2017-06-01 18:19:03 +02:00
|
|
|
|
2017-06-01 18:29:10 +02:00
|
|
|
return d.setDiff(key, value, false)
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
2017-05-31 06:34:02 +02:00
|
|
|
// SetNewComputed functions like SetNew, except that it blanks out a new value
|
|
|
|
// and marks it as computed.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
//
|
2017-05-31 06:50:31 +02:00
|
|
|
// This function is only allowed on computed attributes.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
func (d *ResourceDiff) SetNewComputed(key string) error {
|
2018-09-26 21:38:38 +02:00
|
|
|
if err := d.checkKey(key, "SetNewComputed", false); err != nil {
|
2017-06-01 18:19:03 +02:00
|
|
|
return err
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
2017-06-01 18:19:03 +02:00
|
|
|
|
2017-06-01 18:29:10 +02:00
|
|
|
return d.setDiff(key, nil, true)
|
2017-05-28 03:17:41 +02:00
|
|
|
}
|
|
|
|
|
2017-05-31 17:03:29 +02:00
|
|
|
// setDiff performs common diff setting behaviour.
|
2017-06-01 18:29:10 +02:00
|
|
|
func (d *ResourceDiff) setDiff(key string, new interface{}, computed bool) error {
|
2017-05-28 03:17:41 +02:00
|
|
|
if err := d.clear(key); err != nil {
|
2017-05-25 18:45:31 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
if err := d.newWriter.WriteField(strings.Split(key, "."), new, computed); err != nil {
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
return fmt.Errorf("Cannot set new diff value for key %s: %s", key, err)
|
|
|
|
}
|
|
|
|
|
2017-05-25 19:03:37 +02:00
|
|
|
d.updatedKeys[key] = true
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
return nil
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ForceNew force-flags ForceNew in the schema for a specific key, and
|
2017-07-05 16:05:37 +02:00
|
|
|
// re-calculates its diff, effectively causing this attribute to force a new
|
|
|
|
// resource.
|
|
|
|
//
|
|
|
|
// Keep in mind that forcing a new resource will force a second run of the
|
|
|
|
// resource's CustomizeDiff function (with a new ResourceDiff) once the current
|
|
|
|
// one has completed. This second run is performed without state. This behavior
|
|
|
|
// will be the same as if a new resource is being created and is performed to
|
|
|
|
// ensure that the diff looks like the diff for a new resource as much as
|
|
|
|
// possible. CustomizeDiff should expect such a scenario and act correctly.
|
|
|
|
//
|
|
|
|
// This function is a no-op/error if there is no diff.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
//
|
|
|
|
// Note that the change to schema is permanent for the lifecycle of this
|
2017-05-28 03:17:41 +02:00
|
|
|
// specific ResourceDiff instance.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
func (d *ResourceDiff) ForceNew(key string) error {
|
|
|
|
if !d.HasChange(key) {
|
2017-06-01 18:19:03 +02:00
|
|
|
return fmt.Errorf("ForceNew: No changes for %s", key)
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
2018-02-28 13:55:14 +01:00
|
|
|
keyParts := strings.Split(key, ".")
|
|
|
|
var schema *Schema
|
|
|
|
schemaL := addrToSchema(keyParts, d.schema)
|
|
|
|
if len(schemaL) > 0 {
|
|
|
|
schema = schemaL[len(schemaL)-1]
|
|
|
|
} else {
|
|
|
|
return fmt.Errorf("ForceNew: %s is not a valid key", key)
|
|
|
|
}
|
|
|
|
|
|
|
|
schema.ForceNew = true
|
|
|
|
|
2018-04-07 22:06:47 +02:00
|
|
|
// Flag this for a re-diff. Don't save any values to guarantee that existing
|
|
|
|
// diffs aren't messed with, as this gets messy when dealing with complex
|
|
|
|
// structures, zero values, etc.
|
|
|
|
d.forcedNewKeys[keyParts[0]] = true
|
|
|
|
|
|
|
|
return nil
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get hands off to ResourceData.Get.
|
|
|
|
func (d *ResourceDiff) Get(key string) interface{} {
|
2017-05-25 18:31:31 +02:00
|
|
|
r, _ := d.GetOk(key)
|
|
|
|
return r
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// GetChange gets the change between the state and diff, checking first to see
|
|
|
|
// if a overridden diff exists.
|
|
|
|
//
|
|
|
|
// This implementation differs from ResourceData's in the way that we first get
|
|
|
|
// results from the exact levels for the new diff, then from state and diff as
|
|
|
|
// per normal.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
func (d *ResourceDiff) GetChange(key string) (interface{}, interface{}) {
|
2017-12-20 00:46:58 +01:00
|
|
|
old, new, _ := d.getChange(key)
|
2017-05-25 18:31:31 +02:00
|
|
|
return old.Value, new.Value
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// GetOk functions the same way as ResourceData.GetOk, but it also checks the
|
|
|
|
// new diff levels to provide data consistent with the current state of the
|
|
|
|
// customized diff.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
func (d *ResourceDiff) GetOk(key string) (interface{}, bool) {
|
2017-05-31 17:03:29 +02:00
|
|
|
r := d.get(strings.Split(key, "."), "newDiff")
|
2017-05-25 18:31:31 +02:00
|
|
|
exists := r.Exists && !r.Computed
|
|
|
|
if exists {
|
|
|
|
// If it exists, we also want to verify it is not the zero-value.
|
|
|
|
value := r.Value
|
|
|
|
zero := r.Schema.Type.Zero()
|
|
|
|
|
|
|
|
if eq, ok := value.(Equal); ok {
|
|
|
|
exists = !eq.Equal(zero)
|
|
|
|
} else {
|
|
|
|
exists = !reflect.DeepEqual(value, zero)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.Value, exists
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
2018-03-21 22:15:06 +01:00
|
|
|
// GetOkExists functions the same way as GetOkExists within ResourceData, but
|
|
|
|
// it also checks the new diff levels to provide data consistent with the
|
|
|
|
// current state of the customized diff.
|
2018-03-30 00:13:26 +02:00
|
|
|
//
|
|
|
|
// This is nearly the same function as GetOk, yet it does not check
|
|
|
|
// for the zero value of the attribute's type. This allows for attributes
|
|
|
|
// without a default, to fully check for a literal assignment, regardless
|
|
|
|
// of the zero-value for that type.
|
2018-03-21 22:15:06 +01:00
|
|
|
func (d *ResourceDiff) GetOkExists(key string) (interface{}, bool) {
|
|
|
|
r := d.get(strings.Split(key, "."), "newDiff")
|
|
|
|
exists := r.Exists && !r.Computed
|
|
|
|
return r.Value, exists
|
|
|
|
}
|
|
|
|
|
2018-03-30 00:13:26 +02:00
|
|
|
// NewValueKnown returns true if the new value for the given key is available
|
|
|
|
// as its final value at diff time. If the return value is false, this means
|
|
|
|
// either the value is based of interpolation that was unavailable at diff
|
|
|
|
// time, or that the value was explicitly marked as computed by SetNewComputed.
|
|
|
|
func (d *ResourceDiff) NewValueKnown(key string) bool {
|
2018-03-21 22:15:06 +01:00
|
|
|
r := d.get(strings.Split(key, "."), "newDiff")
|
2018-03-30 00:13:26 +02:00
|
|
|
return !r.Computed
|
2018-03-21 22:15:06 +01:00
|
|
|
}
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// HasChange checks to see if there is a change between state and the diff, or
|
|
|
|
// in the overridden diff.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
func (d *ResourceDiff) HasChange(key string) bool {
|
2017-05-25 18:31:31 +02:00
|
|
|
old, new := d.GetChange(key)
|
|
|
|
|
|
|
|
// If the type implements the Equal interface, then call that
|
|
|
|
// instead of just doing a reflect.DeepEqual. An example where this is
|
|
|
|
// needed is *Set
|
|
|
|
if eq, ok := old.(Equal); ok {
|
|
|
|
return !eq.Equal(new)
|
|
|
|
}
|
|
|
|
|
|
|
|
return !reflect.DeepEqual(old, new)
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// Id returns the ID of this resource.
|
|
|
|
//
|
|
|
|
// Note that technically, ID does not change during diffs (it either has
|
|
|
|
// already changed in the refresh, or will change on update), hence we do not
|
|
|
|
// support updating the ID or fetching it from anything else other than state.
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
func (d *ResourceDiff) Id() string {
|
2017-05-25 18:31:31 +02:00
|
|
|
var result string
|
|
|
|
|
|
|
|
if d.state != nil {
|
|
|
|
result = d.state.ID
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
// getChange gets values from two different levels, designed for use in
|
|
|
|
// diffChange, HasChange, and GetChange.
|
|
|
|
//
|
|
|
|
// This implementation differs from ResourceData's in the way that we first get
|
|
|
|
// results from the exact levels for the new diff, then from state and diff as
|
|
|
|
// per normal.
|
2017-12-20 00:46:58 +01:00
|
|
|
func (d *ResourceDiff) getChange(key string) (getResult, getResult, bool) {
|
2017-05-31 17:03:29 +02:00
|
|
|
old := d.get(strings.Split(key, "."), "state")
|
|
|
|
var new getResult
|
|
|
|
for p := range d.updatedKeys {
|
|
|
|
if childAddrOf(key, p) {
|
|
|
|
new = d.getExact(strings.Split(key, "."), "newDiff")
|
2017-12-20 00:46:58 +01:00
|
|
|
return old, new, true
|
2017-05-31 17:03:29 +02:00
|
|
|
}
|
2017-05-25 18:31:31 +02:00
|
|
|
}
|
2017-05-31 17:03:29 +02:00
|
|
|
new = d.get(strings.Split(key, "."), "newDiff")
|
2017-12-20 00:46:58 +01:00
|
|
|
return old, new, false
|
2017-05-25 18:31:31 +02:00
|
|
|
}
|
|
|
|
|
2018-04-07 22:06:47 +02:00
|
|
|
// removed checks to see if the key is present in the existing, pre-customized
|
|
|
|
// diff and if it was marked as NewRemoved.
|
|
|
|
func (d *ResourceDiff) removed(k string) bool {
|
|
|
|
diff, ok := d.diff.Attributes[k]
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return diff.NewRemoved
|
|
|
|
}
|
|
|
|
|
2017-05-25 18:31:31 +02:00
|
|
|
// get performs the appropriate multi-level reader logic for ResourceDiff,
|
|
|
|
// starting at source. Refer to newResourceDiff for the level order.
|
|
|
|
func (d *ResourceDiff) get(addr []string, source string) getResult {
|
|
|
|
result, err := d.multiReader.ReadFieldMerge(addr, source)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return d.finalizeResult(addr, result)
|
|
|
|
}
|
|
|
|
|
|
|
|
// getExact gets an attribute from the exact level referenced by source.
|
|
|
|
func (d *ResourceDiff) getExact(addr []string, source string) getResult {
|
|
|
|
result, err := d.multiReader.ReadFieldExact(addr, source)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return d.finalizeResult(addr, result)
|
|
|
|
}
|
|
|
|
|
|
|
|
// finalizeResult does some post-processing of the result produced by get and getExact.
|
|
|
|
func (d *ResourceDiff) finalizeResult(addr []string, result FieldReadResult) getResult {
|
|
|
|
// If the result doesn't exist, then we set the value to the zero value
|
|
|
|
var schema *Schema
|
|
|
|
if schemaL := addrToSchema(addr, d.schema); len(schemaL) > 0 {
|
|
|
|
schema = schemaL[len(schemaL)-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.Value == nil && schema != nil {
|
|
|
|
result.Value = result.ValueOrZero(schema)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transform the FieldReadResult into a getResult. It might be worth
|
|
|
|
// merging these two structures one day.
|
|
|
|
return getResult{
|
|
|
|
Value: result.Value,
|
|
|
|
ValueProcessed: result.ValueProcessed,
|
|
|
|
Computed: result.Computed,
|
|
|
|
Exists: result.Exists,
|
|
|
|
Schema: schema,
|
|
|
|
}
|
helper/schema: New ResourceDiff object
This adds a new object, ResourceDiff, to the schema package. This
object, in conjunction with a function defined in CustomizeDiff in the
resource schema, allows for the in-flight customization of a Terraform
diff. This helps support use cases such as when there are necessary
changes to a resource that cannot be detected in config, such as via
computed fields (most of the utility in this object works on computed
fields only). It also allows for a wholesale wipe of the diff to allow
for diff logic completely offloaded to an external API, if it is a
better use case for a specific provider.
As part of this work, many internal diff functions have been moved to
use a special resourceDiffer interface, to allow for shared
functionality between ResourceDiff and ResourceData. This may be
extended to the DiffSuppressFunc as well which would restrict use of
ResourceData in DiffSuppressFunc to generally read-only fields.
This work is not yet in its final state - CustomizeDiff is not yet
implemented in the general diff workflow, new functions may be added
(notably Clear() for a single key), and functionality may be altered.
Tests will follow as well.
2017-05-23 06:32:59 +02:00
|
|
|
}
|
2017-05-31 17:03:29 +02:00
|
|
|
|
|
|
|
// childAddrOf does a comparison of two addresses to see if one is the child of
|
|
|
|
// the other.
|
|
|
|
func childAddrOf(child, parent string) bool {
|
|
|
|
cs := strings.Split(child, ".")
|
|
|
|
ps := strings.Split(parent, ".")
|
2017-05-31 18:35:53 +02:00
|
|
|
if len(ps) > len(cs) {
|
|
|
|
return false
|
|
|
|
}
|
2017-05-31 17:03:29 +02:00
|
|
|
return reflect.DeepEqual(ps, cs[:len(ps)])
|
|
|
|
}
|
2017-06-01 18:19:03 +02:00
|
|
|
|
|
|
|
// checkKey checks the key to make sure it exists and is computed.
|
2018-09-26 21:38:38 +02:00
|
|
|
func (d *ResourceDiff) checkKey(key, caller string, nested bool) error {
|
2018-09-06 02:29:03 +02:00
|
|
|
var schema *Schema
|
2018-09-26 21:38:38 +02:00
|
|
|
if nested {
|
|
|
|
keyParts := strings.Split(key, ".")
|
|
|
|
schemaL := addrToSchema(keyParts, d.schema)
|
|
|
|
if len(schemaL) > 0 {
|
|
|
|
schema = schemaL[len(schemaL)-1]
|
|
|
|
}
|
2018-09-06 02:29:03 +02:00
|
|
|
} else {
|
2018-09-26 21:38:38 +02:00
|
|
|
s, ok := d.schema[key]
|
|
|
|
if ok {
|
|
|
|
schema = s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if schema == nil {
|
2017-06-01 18:19:03 +02:00
|
|
|
return fmt.Errorf("%s: invalid key: %s", caller, key)
|
|
|
|
}
|
2018-09-06 02:29:03 +02:00
|
|
|
if !schema.Computed {
|
2017-06-01 18:19:03 +02:00
|
|
|
return fmt.Errorf("%s only operates on computed keys - %s is not one", caller, key)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|