diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/eval_read_data.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/terraform/eval_read_data.go | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/eval_read_data.go b/vendor/github.com/hashicorp/terraform/terraform/eval_read_data.go new file mode 100644 index 00000000..fb85a284 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/terraform/eval_read_data.go @@ -0,0 +1,139 @@ +package terraform + +import ( + "fmt" +) + +// EvalReadDataDiff is an EvalNode implementation that executes a data +// resource's ReadDataDiff method to discover what attributes it exports. +type EvalReadDataDiff struct { + Provider *ResourceProvider + Output **InstanceDiff + OutputState **InstanceState + Config **ResourceConfig + Info *InstanceInfo + + // Set Previous when re-evaluating diff during apply, to ensure that + // the "Destroy" flag is preserved. + Previous **InstanceDiff +} + +func (n *EvalReadDataDiff) Eval(ctx EvalContext) (interface{}, error) { + // TODO: test + + err := ctx.Hook(func(h Hook) (HookAction, error) { + return h.PreDiff(n.Info, nil) + }) + if err != nil { + return nil, err + } + + var diff *InstanceDiff + + if n.Previous != nil && *n.Previous != nil && (*n.Previous).GetDestroy() { + // If we're re-diffing for a diff that was already planning to + // destroy, then we'll just continue with that plan. + diff = &InstanceDiff{Destroy: true} + } else { + provider := *n.Provider + config := *n.Config + + var err error + diff, err = provider.ReadDataDiff(n.Info, config) + if err != nil { + return nil, err + } + if diff == nil { + diff = new(InstanceDiff) + } + + // if id isn't explicitly set then it's always computed, because we're + // always "creating a new resource". + diff.init() + if _, ok := diff.Attributes["id"]; !ok { + diff.SetAttribute("id", &ResourceAttrDiff{ + Old: "", + NewComputed: true, + RequiresNew: true, + Type: DiffAttrOutput, + }) + } + } + + err = ctx.Hook(func(h Hook) (HookAction, error) { + return h.PostDiff(n.Info, diff) + }) + if err != nil { + return nil, err + } + + *n.Output = diff + + if n.OutputState != nil { + state := &InstanceState{} + *n.OutputState = state + + // Apply the diff to the returned state, so the state includes + // any attribute values that are not computed. + if !diff.Empty() && n.OutputState != nil { + *n.OutputState = state.MergeDiff(diff) + } + } + + return nil, nil +} + +// EvalReadDataApply is an EvalNode implementation that executes a data +// resource's ReadDataApply method to read data from the data source. +type EvalReadDataApply struct { + Provider *ResourceProvider + Output **InstanceState + Diff **InstanceDiff + Info *InstanceInfo +} + +func (n *EvalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { + // TODO: test + provider := *n.Provider + diff := *n.Diff + + // If the diff is for *destroying* this resource then we'll + // just drop its state and move on, since data resources don't + // support an actual "destroy" action. + if diff != nil && diff.GetDestroy() { + if n.Output != nil { + *n.Output = nil + } + return nil, nil + } + + // For the purpose of external hooks we present a data apply as a + // "Refresh" rather than an "Apply" because creating a data source + // is presented to users/callers as a "read" operation. + err := ctx.Hook(func(h Hook) (HookAction, error) { + // We don't have a state yet, so we'll just give the hook an + // empty one to work with. + return h.PreRefresh(n.Info, &InstanceState{}) + }) + if err != nil { + return nil, err + } + + state, err := provider.ReadDataApply(n.Info, diff) + if err != nil { + return nil, fmt.Errorf("%s: %s", n.Info.Id, err) + } + + err = ctx.Hook(func(h Hook) (HookAction, error) { + return h.PostRefresh(n.Info, state) + }) + if err != nil { + return nil, err + } + + if n.Output != nil { + *n.Output = state + } + + return nil, nil +} |