]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/terraform/eval_refresh.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / eval_refresh.go
1 package terraform
2
3 import (
4 "fmt"
5 "log"
6
7 "github.com/zclconf/go-cty/cty"
8
9 "github.com/hashicorp/terraform/addrs"
10 "github.com/hashicorp/terraform/providers"
11 "github.com/hashicorp/terraform/states"
12 "github.com/hashicorp/terraform/tfdiags"
13 )
14
15 // EvalRefresh is an EvalNode implementation that does a refresh for
16 // a resource.
17 type EvalRefresh struct {
18 Addr addrs.ResourceInstance
19 ProviderAddr addrs.AbsProviderConfig
20 Provider *providers.Interface
21 ProviderSchema **ProviderSchema
22 State **states.ResourceInstanceObject
23 Output **states.ResourceInstanceObject
24 }
25
26 // TODO: test
27 func (n *EvalRefresh) Eval(ctx EvalContext) (interface{}, error) {
28 state := *n.State
29 absAddr := n.Addr.Absolute(ctx.Path())
30
31 var diags tfdiags.Diagnostics
32
33 // If we have no state, we don't do any refreshing
34 if state == nil {
35 log.Printf("[DEBUG] refresh: %s: no state, so not refreshing", n.Addr.Absolute(ctx.Path()))
36 return nil, diags.ErrWithWarnings()
37 }
38
39 schema, _ := (*n.ProviderSchema).SchemaForResourceAddr(n.Addr.ContainingResource())
40 if schema == nil {
41 // Should be caught during validation, so we don't bother with a pretty error here
42 return nil, fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type)
43 }
44
45 // Call pre-refresh hook
46 err := ctx.Hook(func(h Hook) (HookAction, error) {
47 return h.PreRefresh(absAddr, states.CurrentGen, state.Value)
48 })
49 if err != nil {
50 return nil, diags.ErrWithWarnings()
51 }
52
53 // Refresh!
54 priorVal := state.Value
55 req := providers.ReadResourceRequest{
56 TypeName: n.Addr.Resource.Type,
57 PriorState: priorVal,
58 }
59
60 provider := *n.Provider
61 resp := provider.ReadResource(req)
62 diags = diags.Append(resp.Diagnostics)
63 if diags.HasErrors() {
64 return nil, diags.Err()
65 }
66
67 if resp.NewState == cty.NilVal {
68 // This ought not to happen in real cases since it's not possible to
69 // send NilVal over the plugin RPC channel, but it can come up in
70 // tests due to sloppy mocking.
71 panic("new state is cty.NilVal")
72 }
73
74 for _, err := range resp.NewState.Type().TestConformance(schema.ImpliedType()) {
75 diags = diags.Append(tfdiags.Sourceless(
76 tfdiags.Error,
77 "Provider produced invalid object",
78 fmt.Sprintf(
79 "Provider %q planned an invalid value for %s during refresh: %s.\n\nThis is a bug in the provider, which should be reported in the provider's own issue tracker.",
80 n.ProviderAddr.ProviderConfig.Type, absAddr, tfdiags.FormatError(err),
81 ),
82 ))
83 }
84 if diags.HasErrors() {
85 return nil, diags.Err()
86 }
87
88 newState := state.DeepCopy()
89 newState.Value = resp.NewState
90
91 // Call post-refresh hook
92 err = ctx.Hook(func(h Hook) (HookAction, error) {
93 return h.PostRefresh(absAddr, states.CurrentGen, priorVal, newState.Value)
94 })
95 if err != nil {
96 return nil, err
97 }
98
99 if n.Output != nil {
100 *n.Output = newState
101 }
102
103 return nil, diags.ErrWithWarnings()
104 }