]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - 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
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
4 "fmt"
5 "log"
107c1cdb
ND
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"
bae9f6d2
JC
13)
14
15// EvalRefresh is an EvalNode implementation that does a refresh for
16// a resource.
17type EvalRefresh struct {
107c1cdb
ND
18 Addr addrs.ResourceInstance
19 ProviderAddr addrs.AbsProviderConfig
20 Provider *providers.Interface
21 ProviderSchema **ProviderSchema
22 State **states.ResourceInstanceObject
23 Output **states.ResourceInstanceObject
bae9f6d2
JC
24}
25
26// TODO: test
27func (n *EvalRefresh) Eval(ctx EvalContext) (interface{}, error) {
bae9f6d2 28 state := *n.State
107c1cdb
ND
29 absAddr := n.Addr.Absolute(ctx.Path())
30
31 var diags tfdiags.Diagnostics
bae9f6d2
JC
32
33 // If we have no state, we don't do any refreshing
34 if state == nil {
107c1cdb
ND
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)
bae9f6d2
JC
43 }
44
45 // Call pre-refresh hook
46 err := ctx.Hook(func(h Hook) (HookAction, error) {
107c1cdb 47 return h.PreRefresh(absAddr, states.CurrentGen, state.Value)
bae9f6d2
JC
48 })
49 if err != nil {
107c1cdb 50 return nil, diags.ErrWithWarnings()
bae9f6d2
JC
51 }
52
53 // Refresh!
107c1cdb
ND
54 priorVal := state.Value
55 req := providers.ReadResourceRequest{
56 TypeName: n.Addr.Resource.Type,
57 PriorState: priorVal,
bae9f6d2
JC
58 }
59
107c1cdb
ND
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
bae9f6d2
JC
91 // Call post-refresh hook
92 err = ctx.Hook(func(h Hook) (HookAction, error) {
107c1cdb 93 return h.PostRefresh(absAddr, states.CurrentGen, priorVal, newState.Value)
bae9f6d2
JC
94 })
95 if err != nil {
96 return nil, err
97 }
98
99 if n.Output != nil {
107c1cdb 100 *n.Output = newState
bae9f6d2
JC
101 }
102
107c1cdb 103 return nil, diags.ErrWithWarnings()
bae9f6d2 104}