]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
107c1cdb ND |
3 | import ( |
4 | "github.com/zclconf/go-cty/cty" | |
5 | ||
6 | "github.com/hashicorp/terraform/addrs" | |
7 | "github.com/hashicorp/terraform/plans" | |
8 | "github.com/hashicorp/terraform/providers" | |
9 | "github.com/hashicorp/terraform/states" | |
10 | ) | |
11 | ||
bae9f6d2 JC |
12 | // HookAction is an enum of actions that can be taken as a result of a hook |
13 | // callback. This allows you to modify the behavior of Terraform at runtime. | |
14 | type HookAction byte | |
15 | ||
16 | const ( | |
17 | // HookActionContinue continues with processing as usual. | |
18 | HookActionContinue HookAction = iota | |
19 | ||
20 | // HookActionHalt halts immediately: no more hooks are processed | |
21 | // and the action that Terraform was about to take is cancelled. | |
22 | HookActionHalt | |
23 | ) | |
24 | ||
25 | // Hook is the interface that must be implemented to hook into various | |
26 | // parts of Terraform, allowing you to inspect or change behavior at runtime. | |
27 | // | |
28 | // There are MANY hook points into Terraform. If you only want to implement | |
29 | // some hook points, but not all (which is the likely case), then embed the | |
30 | // NilHook into your struct, which implements all of the interface but does | |
31 | // nothing. Then, override only the functions you want to implement. | |
32 | type Hook interface { | |
107c1cdb ND |
33 | // PreApply and PostApply are called before and after an action for a |
34 | // single instance is applied. The error argument in PostApply is the | |
bae9f6d2 | 35 | // error, if any, that was returned from the provider Apply call itself. |
107c1cdb ND |
36 | PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) |
37 | PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error) | |
38 | ||
39 | // PreDiff and PostDiff are called before and after a provider is given | |
40 | // the opportunity to customize the proposed new state to produce the | |
41 | // planned new state. | |
42 | PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error) | |
43 | PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) | |
44 | ||
45 | // The provisioning hooks signal both the overall start end end of | |
46 | // provisioning for a particular instance and of each of the individual | |
47 | // configured provisioners for each instance. The sequence of these | |
48 | // for a given instance might look something like this: | |
bae9f6d2 | 49 | // |
107c1cdb ND |
50 | // PreProvisionInstance(aws_instance.foo[1], ...) |
51 | // PreProvisionInstanceStep(aws_instance.foo[1], "file") | |
52 | // PostProvisionInstanceStep(aws_instance.foo[1], "file", nil) | |
53 | // PreProvisionInstanceStep(aws_instance.foo[1], "remote-exec") | |
54 | // ProvisionOutput(aws_instance.foo[1], "remote-exec", "Installing foo...") | |
55 | // ProvisionOutput(aws_instance.foo[1], "remote-exec", "Configuring bar...") | |
56 | // PostProvisionInstanceStep(aws_instance.foo[1], "remote-exec", nil) | |
57 | // PostProvisionInstance(aws_instance.foo[1], ...) | |
58 | // | |
59 | // ProvisionOutput is called with output sent back by the provisioners. | |
60 | // This will be called multiple times as output comes in, with each call | |
61 | // representing one line of output. It cannot control whether the | |
62 | // provisioner continues running. | |
63 | PreProvisionInstance(addr addrs.AbsResourceInstance, state cty.Value) (HookAction, error) | |
64 | PostProvisionInstance(addr addrs.AbsResourceInstance, state cty.Value) (HookAction, error) | |
65 | PreProvisionInstanceStep(addr addrs.AbsResourceInstance, typeName string) (HookAction, error) | |
66 | PostProvisionInstanceStep(addr addrs.AbsResourceInstance, typeName string, err error) (HookAction, error) | |
67 | ProvisionOutput(addr addrs.AbsResourceInstance, typeName string, line string) | |
bae9f6d2 JC |
68 | |
69 | // PreRefresh and PostRefresh are called before and after a single | |
70 | // resource state is refreshed, respectively. | |
107c1cdb ND |
71 | PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (HookAction, error) |
72 | PostRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value, newState cty.Value) (HookAction, error) | |
bae9f6d2 JC |
73 | |
74 | // PreImportState and PostImportState are called before and after | |
107c1cdb ND |
75 | // (respectively) each state import operation for a given resource address. |
76 | PreImportState(addr addrs.AbsResourceInstance, importID string) (HookAction, error) | |
77 | PostImportState(addr addrs.AbsResourceInstance, imported []providers.ImportedResource) (HookAction, error) | |
78 | ||
79 | // PostStateUpdate is called each time the state is updated. It receives | |
80 | // a deep copy of the state, which it may therefore access freely without | |
81 | // any need for locks to protect from concurrent writes from the caller. | |
82 | PostStateUpdate(new *states.State) (HookAction, error) | |
bae9f6d2 JC |
83 | } |
84 | ||
85 | // NilHook is a Hook implementation that does nothing. It exists only to | |
86 | // simplify implementing hooks. You can embed this into your Hook implementation | |
87 | // and only implement the functions you are interested in. | |
88 | type NilHook struct{} | |
89 | ||
107c1cdb ND |
90 | var _ Hook = (*NilHook)(nil) |
91 | ||
92 | func (*NilHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) { | |
bae9f6d2 JC |
93 | return HookActionContinue, nil |
94 | } | |
95 | ||
107c1cdb | 96 | func (*NilHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, err error) (HookAction, error) { |
bae9f6d2 JC |
97 | return HookActionContinue, nil |
98 | } | |
99 | ||
107c1cdb | 100 | func (*NilHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (HookAction, error) { |
bae9f6d2 JC |
101 | return HookActionContinue, nil |
102 | } | |
103 | ||
107c1cdb | 104 | func (*NilHook) PostDiff(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) { |
bae9f6d2 JC |
105 | return HookActionContinue, nil |
106 | } | |
107 | ||
107c1cdb | 108 | func (*NilHook) PreProvisionInstance(addr addrs.AbsResourceInstance, state cty.Value) (HookAction, error) { |
bae9f6d2 JC |
109 | return HookActionContinue, nil |
110 | } | |
111 | ||
107c1cdb | 112 | func (*NilHook) PostProvisionInstance(addr addrs.AbsResourceInstance, state cty.Value) (HookAction, error) { |
bae9f6d2 JC |
113 | return HookActionContinue, nil |
114 | } | |
115 | ||
107c1cdb | 116 | func (*NilHook) PreProvisionInstanceStep(addr addrs.AbsResourceInstance, typeName string) (HookAction, error) { |
bae9f6d2 JC |
117 | return HookActionContinue, nil |
118 | } | |
119 | ||
107c1cdb | 120 | func (*NilHook) PostProvisionInstanceStep(addr addrs.AbsResourceInstance, typeName string, err error) (HookAction, error) { |
bae9f6d2 JC |
121 | return HookActionContinue, nil |
122 | } | |
123 | ||
107c1cdb | 124 | func (*NilHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName string, line string) { |
bae9f6d2 JC |
125 | } |
126 | ||
107c1cdb | 127 | func (*NilHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (HookAction, error) { |
bae9f6d2 JC |
128 | return HookActionContinue, nil |
129 | } | |
130 | ||
107c1cdb | 131 | func (*NilHook) PostRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value, newState cty.Value) (HookAction, error) { |
bae9f6d2 JC |
132 | return HookActionContinue, nil |
133 | } | |
134 | ||
107c1cdb | 135 | func (*NilHook) PreImportState(addr addrs.AbsResourceInstance, importID string) (HookAction, error) { |
bae9f6d2 JC |
136 | return HookActionContinue, nil |
137 | } | |
138 | ||
107c1cdb | 139 | func (*NilHook) PostImportState(addr addrs.AbsResourceInstance, imported []providers.ImportedResource) (HookAction, error) { |
bae9f6d2 JC |
140 | return HookActionContinue, nil |
141 | } | |
142 | ||
107c1cdb | 143 | func (*NilHook) PostStateUpdate(new *states.State) (HookAction, error) { |
bae9f6d2 JC |
144 | return HookActionContinue, nil |
145 | } | |
146 | ||
147 | // handleHook turns hook actions into panics. This lets you use the | |
148 | // panic/recover mechanism in Go as a flow control mechanism for hook | |
149 | // actions. | |
150 | func handleHook(a HookAction, err error) { | |
151 | if err != nil { | |
152 | // TODO: handle errors | |
153 | } | |
154 | ||
155 | switch a { | |
156 | case HookActionContinue: | |
157 | return | |
158 | case HookActionHalt: | |
159 | panic(HookActionHalt) | |
160 | } | |
161 | } |