github.com/ricardclau/terraform@v0.6.17-0.20160519222547-283e3ae6b5a9/terraform/eval_read_data.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  // EvalReadDataDiff is an EvalNode implementation that executes a data
     8  // resource's ReadDataDiff method to discover what attributes it exports.
     9  type EvalReadDataDiff struct {
    10  	Provider    *ResourceProvider
    11  	Output      **InstanceDiff
    12  	OutputState **InstanceState
    13  	Config      **ResourceConfig
    14  	Info        *InstanceInfo
    15  }
    16  
    17  func (n *EvalReadDataDiff) Eval(ctx EvalContext) (interface{}, error) {
    18  	// TODO: test
    19  	provider := *n.Provider
    20  	config := *n.Config
    21  
    22  	err := ctx.Hook(func(h Hook) (HookAction, error) {
    23  		return h.PreDiff(n.Info, nil)
    24  	})
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  
    29  	diff, err := provider.ReadDataDiff(n.Info, config)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	if diff == nil {
    34  		diff = new(InstanceDiff)
    35  	}
    36  
    37  	// id is always computed, because we're always "creating a new resource"
    38  	diff.init()
    39  	diff.Attributes["id"] = &ResourceAttrDiff{
    40  		Old:         "",
    41  		NewComputed: true,
    42  		RequiresNew: true,
    43  		Type:        DiffAttrOutput,
    44  	}
    45  
    46  	err = ctx.Hook(func(h Hook) (HookAction, error) {
    47  		return h.PostDiff(n.Info, diff)
    48  	})
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	*n.Output = diff
    54  
    55  	if n.OutputState != nil {
    56  		state := &InstanceState{}
    57  		*n.OutputState = state
    58  
    59  		// Apply the diff to the returned state, so the state includes
    60  		// any attribute values that are not computed.
    61  		if !diff.Empty() && n.OutputState != nil {
    62  			*n.OutputState = state.MergeDiff(diff)
    63  		}
    64  	}
    65  
    66  	return nil, nil
    67  }
    68  
    69  // EvalReadDataApply is an EvalNode implementation that executes a data
    70  // resource's ReadDataApply method to read data from the data source.
    71  type EvalReadDataApply struct {
    72  	Provider *ResourceProvider
    73  	Output   **InstanceState
    74  	Diff     **InstanceDiff
    75  	Info     *InstanceInfo
    76  }
    77  
    78  func (n *EvalReadDataApply) Eval(ctx EvalContext) (interface{}, error) {
    79  	// TODO: test
    80  	provider := *n.Provider
    81  	diff := *n.Diff
    82  
    83  	// If the diff is for *destroying* this resource then we'll
    84  	// just drop its state and move on, since data resources don't
    85  	// support an actual "destroy" action.
    86  	if diff.Destroy {
    87  		if n.Output != nil {
    88  			*n.Output = nil
    89  		}
    90  		return nil, nil
    91  	}
    92  
    93  	// For the purpose of external hooks we present a data apply as a
    94  	// "Refresh" rather than an "Apply" because creating a data source
    95  	// is presented to users/callers as a "read" operation.
    96  	err := ctx.Hook(func(h Hook) (HookAction, error) {
    97  		// We don't have a state yet, so we'll just give the hook an
    98  		// empty one to work with.
    99  		return h.PreRefresh(n.Info, &InstanceState{})
   100  	})
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	state, err := provider.ReadDataApply(n.Info, diff)
   106  	if err != nil {
   107  		return nil, fmt.Errorf("%s: %s", n.Info.Id, err)
   108  	}
   109  
   110  	err = ctx.Hook(func(h Hook) (HookAction, error) {
   111  		return h.PostRefresh(n.Info, state)
   112  	})
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	if n.Output != nil {
   118  		*n.Output = state
   119  	}
   120  
   121  	return nil, nil
   122  }