diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go b/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go new file mode 100644 index 0000000..c1564a2 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go | |||
@@ -0,0 +1,180 @@ | |||
1 | package schema | ||
2 | |||
3 | import ( | ||
4 | "context" | ||
5 | "errors" | ||
6 | "fmt" | ||
7 | "sync" | ||
8 | |||
9 | "github.com/hashicorp/go-multierror" | ||
10 | "github.com/hashicorp/terraform/config" | ||
11 | "github.com/hashicorp/terraform/terraform" | ||
12 | ) | ||
13 | |||
14 | // Provisioner represents a resource provisioner in Terraform and properly | ||
15 | // implements all of the ResourceProvisioner API. | ||
16 | // | ||
17 | // This higher level structure makes it much easier to implement a new or | ||
18 | // custom provisioner for Terraform. | ||
19 | // | ||
20 | // The function callbacks for this structure are all passed a context object. | ||
21 | // This context object has a number of pre-defined values that can be accessed | ||
22 | // via the global functions defined in context.go. | ||
23 | type Provisioner struct { | ||
24 | // ConnSchema is the schema for the connection settings for this | ||
25 | // provisioner. | ||
26 | // | ||
27 | // The keys of this map are the configuration keys, and the value is | ||
28 | // the schema describing the value of the configuration. | ||
29 | // | ||
30 | // NOTE: The value of connection keys can only be strings for now. | ||
31 | ConnSchema map[string]*Schema | ||
32 | |||
33 | // Schema is the schema for the usage of this provisioner. | ||
34 | // | ||
35 | // The keys of this map are the configuration keys, and the value is | ||
36 | // the schema describing the value of the configuration. | ||
37 | Schema map[string]*Schema | ||
38 | |||
39 | // ApplyFunc is the function for executing the provisioner. This is required. | ||
40 | // It is given a context. See the Provisioner struct docs for more | ||
41 | // information. | ||
42 | ApplyFunc func(ctx context.Context) error | ||
43 | |||
44 | stopCtx context.Context | ||
45 | stopCtxCancel context.CancelFunc | ||
46 | stopOnce sync.Once | ||
47 | } | ||
48 | |||
49 | // Keys that can be used to access data in the context parameters for | ||
50 | // Provisioners. | ||
51 | var ( | ||
52 | connDataInvalid = contextKey("data invalid") | ||
53 | |||
54 | // This returns a *ResourceData for the connection information. | ||
55 | // Guaranteed to never be nil. | ||
56 | ProvConnDataKey = contextKey("provider conn data") | ||
57 | |||
58 | // This returns a *ResourceData for the config information. | ||
59 | // Guaranteed to never be nil. | ||
60 | ProvConfigDataKey = contextKey("provider config data") | ||
61 | |||
62 | // This returns a terraform.UIOutput. Guaranteed to never be nil. | ||
63 | ProvOutputKey = contextKey("provider output") | ||
64 | |||
65 | // This returns the raw InstanceState passed to Apply. Guaranteed to | ||
66 | // be set, but may be nil. | ||
67 | ProvRawStateKey = contextKey("provider raw state") | ||
68 | ) | ||
69 | |||
70 | // InternalValidate should be called to validate the structure | ||
71 | // of the provisioner. | ||
72 | // | ||
73 | // This should be called in a unit test to verify before release that this | ||
74 | // structure is properly configured for use. | ||
75 | func (p *Provisioner) InternalValidate() error { | ||
76 | if p == nil { | ||
77 | return errors.New("provisioner is nil") | ||
78 | } | ||
79 | |||
80 | var validationErrors error | ||
81 | { | ||
82 | sm := schemaMap(p.ConnSchema) | ||
83 | if err := sm.InternalValidate(sm); err != nil { | ||
84 | validationErrors = multierror.Append(validationErrors, err) | ||
85 | } | ||
86 | } | ||
87 | |||
88 | { | ||
89 | sm := schemaMap(p.Schema) | ||
90 | if err := sm.InternalValidate(sm); err != nil { | ||
91 | validationErrors = multierror.Append(validationErrors, err) | ||
92 | } | ||
93 | } | ||
94 | |||
95 | if p.ApplyFunc == nil { | ||
96 | validationErrors = multierror.Append(validationErrors, fmt.Errorf( | ||
97 | "ApplyFunc must not be nil")) | ||
98 | } | ||
99 | |||
100 | return validationErrors | ||
101 | } | ||
102 | |||
103 | // StopContext returns a context that checks whether a provisioner is stopped. | ||
104 | func (p *Provisioner) StopContext() context.Context { | ||
105 | p.stopOnce.Do(p.stopInit) | ||
106 | return p.stopCtx | ||
107 | } | ||
108 | |||
109 | func (p *Provisioner) stopInit() { | ||
110 | p.stopCtx, p.stopCtxCancel = context.WithCancel(context.Background()) | ||
111 | } | ||
112 | |||
113 | // Stop implementation of terraform.ResourceProvisioner interface. | ||
114 | func (p *Provisioner) Stop() error { | ||
115 | p.stopOnce.Do(p.stopInit) | ||
116 | p.stopCtxCancel() | ||
117 | return nil | ||
118 | } | ||
119 | |||
120 | func (p *Provisioner) Validate(c *terraform.ResourceConfig) ([]string, []error) { | ||
121 | return schemaMap(p.Schema).Validate(c) | ||
122 | } | ||
123 | |||
124 | // Apply implementation of terraform.ResourceProvisioner interface. | ||
125 | func (p *Provisioner) Apply( | ||
126 | o terraform.UIOutput, | ||
127 | s *terraform.InstanceState, | ||
128 | c *terraform.ResourceConfig) error { | ||
129 | var connData, configData *ResourceData | ||
130 | |||
131 | { | ||
132 | // We first need to turn the connection information into a | ||
133 | // terraform.ResourceConfig so that we can use that type to more | ||
134 | // easily build a ResourceData structure. We do this by simply treating | ||
135 | // the conn info as configuration input. | ||
136 | raw := make(map[string]interface{}) | ||
137 | if s != nil { | ||
138 | for k, v := range s.Ephemeral.ConnInfo { | ||
139 | raw[k] = v | ||
140 | } | ||
141 | } | ||
142 | |||
143 | c, err := config.NewRawConfig(raw) | ||
144 | if err != nil { | ||
145 | return err | ||
146 | } | ||
147 | |||
148 | sm := schemaMap(p.ConnSchema) | ||
149 | diff, err := sm.Diff(nil, terraform.NewResourceConfig(c)) | ||
150 | if err != nil { | ||
151 | return err | ||
152 | } | ||
153 | connData, err = sm.Data(nil, diff) | ||
154 | if err != nil { | ||
155 | return err | ||
156 | } | ||
157 | } | ||
158 | |||
159 | { | ||
160 | // Build the configuration data. Doing this requires making a "diff" | ||
161 | // even though that's never used. We use that just to get the correct types. | ||
162 | configMap := schemaMap(p.Schema) | ||
163 | diff, err := configMap.Diff(nil, c) | ||
164 | if err != nil { | ||
165 | return err | ||
166 | } | ||
167 | configData, err = configMap.Data(nil, diff) | ||
168 | if err != nil { | ||
169 | return err | ||
170 | } | ||
171 | } | ||
172 | |||
173 | // Build the context and call the function | ||
174 | ctx := p.StopContext() | ||
175 | ctx = context.WithValue(ctx, ProvConnDataKey, connData) | ||
176 | ctx = context.WithValue(ctx, ProvConfigDataKey, configData) | ||
177 | ctx = context.WithValue(ctx, ProvOutputKey, o) | ||
178 | ctx = context.WithValue(ctx, ProvRawStateKey, s) | ||
179 | return p.ApplyFunc(ctx) | ||
180 | } | ||