]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/terraform/resource_provider.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / resource_provider.go
1 package terraform
2
3 import (
4 "fmt"
5
6 "github.com/hashicorp/terraform/tfdiags"
7
8 "github.com/hashicorp/terraform/plugin/discovery"
9 "github.com/hashicorp/terraform/providers"
10 )
11
12 // ResourceProvider is an interface that must be implemented by any
13 // resource provider: the thing that creates and manages the resources in
14 // a Terraform configuration.
15 //
16 // Important implementation note: All returned pointers, such as
17 // *ResourceConfig, *InstanceState, *InstanceDiff, etc. must not point to
18 // shared data. Terraform is highly parallel and assumes that this data is safe
19 // to read/write in parallel so it must be unique references. Note that it is
20 // safe to return arguments as results, however.
21 type ResourceProvider interface {
22 /*********************************************************************
23 * Functions related to the provider
24 *********************************************************************/
25
26 // ProviderSchema returns the config schema for the main provider
27 // configuration, as would appear in a "provider" block in the
28 // configuration files.
29 //
30 // Currently not all providers support schema. Callers must therefore
31 // first call Resources and DataSources and ensure that at least one
32 // resource or data source has the SchemaAvailable flag set.
33 GetSchema(*ProviderSchemaRequest) (*ProviderSchema, error)
34
35 // Input was used prior to v0.12 to ask the provider to prompt the user
36 // for input to complete the configuration.
37 //
38 // From v0.12 onwards this method is never called because Terraform Core
39 // is able to handle the necessary input logic itself based on the
40 // schema returned from GetSchema.
41 Input(UIInput, *ResourceConfig) (*ResourceConfig, error)
42
43 // Validate is called once at the beginning with the raw configuration
44 // (no interpolation done) and can return a list of warnings and/or
45 // errors.
46 //
47 // This is called once with the provider configuration only. It may not
48 // be called at all if no provider configuration is given.
49 //
50 // This should not assume that any values of the configurations are valid.
51 // The primary use case of this call is to check that required keys are
52 // set.
53 Validate(*ResourceConfig) ([]string, []error)
54
55 // Configure configures the provider itself with the configuration
56 // given. This is useful for setting things like access keys.
57 //
58 // This won't be called at all if no provider configuration is given.
59 //
60 // Configure returns an error if it occurred.
61 Configure(*ResourceConfig) error
62
63 // Resources returns all the available resource types that this provider
64 // knows how to manage.
65 Resources() []ResourceType
66
67 // Stop is called when the provider should halt any in-flight actions.
68 //
69 // This can be used to make a nicer Ctrl-C experience for Terraform.
70 // Even if this isn't implemented to do anything (just returns nil),
71 // Terraform will still cleanly stop after the currently executing
72 // graph node is complete. However, this API can be used to make more
73 // efficient halts.
74 //
75 // Stop doesn't have to and shouldn't block waiting for in-flight actions
76 // to complete. It should take any action it wants and return immediately
77 // acknowledging it has received the stop request. Terraform core will
78 // automatically not make any further API calls to the provider soon
79 // after Stop is called (technically exactly once the currently executing
80 // graph nodes are complete).
81 //
82 // The error returned, if non-nil, is assumed to mean that signaling the
83 // stop somehow failed and that the user should expect potentially waiting
84 // a longer period of time.
85 Stop() error
86
87 /*********************************************************************
88 * Functions related to individual resources
89 *********************************************************************/
90
91 // ValidateResource is called once at the beginning with the raw
92 // configuration (no interpolation done) and can return a list of warnings
93 // and/or errors.
94 //
95 // This is called once per resource.
96 //
97 // This should not assume any of the values in the resource configuration
98 // are valid since it is possible they have to be interpolated still.
99 // The primary use case of this call is to check that the required keys
100 // are set and that the general structure is correct.
101 ValidateResource(string, *ResourceConfig) ([]string, []error)
102
103 // Apply applies a diff to a specific resource and returns the new
104 // resource state along with an error.
105 //
106 // If the resource state given has an empty ID, then a new resource
107 // is expected to be created.
108 Apply(
109 *InstanceInfo,
110 *InstanceState,
111 *InstanceDiff) (*InstanceState, error)
112
113 // Diff diffs a resource versus a desired state and returns
114 // a diff.
115 Diff(
116 *InstanceInfo,
117 *InstanceState,
118 *ResourceConfig) (*InstanceDiff, error)
119
120 // Refresh refreshes a resource and updates all of its attributes
121 // with the latest information.
122 Refresh(*InstanceInfo, *InstanceState) (*InstanceState, error)
123
124 /*********************************************************************
125 * Functions related to importing
126 *********************************************************************/
127
128 // ImportState requests that the given resource be imported.
129 //
130 // The returned InstanceState only requires ID be set. Importing
131 // will always call Refresh after the state to complete it.
132 //
133 // IMPORTANT: InstanceState doesn't have the resource type attached
134 // to it. A type must be specified on the state via the Ephemeral
135 // field on the state.
136 //
137 // This function can return multiple states. Normally, an import
138 // will map 1:1 to a physical resource. However, some resources map
139 // to multiple. For example, an AWS security group may contain many rules.
140 // Each rule is represented by a separate resource in Terraform,
141 // therefore multiple states are returned.
142 ImportState(*InstanceInfo, string) ([]*InstanceState, error)
143
144 /*********************************************************************
145 * Functions related to data resources
146 *********************************************************************/
147
148 // ValidateDataSource is called once at the beginning with the raw
149 // configuration (no interpolation done) and can return a list of warnings
150 // and/or errors.
151 //
152 // This is called once per data source instance.
153 //
154 // This should not assume any of the values in the resource configuration
155 // are valid since it is possible they have to be interpolated still.
156 // The primary use case of this call is to check that the required keys
157 // are set and that the general structure is correct.
158 ValidateDataSource(string, *ResourceConfig) ([]string, []error)
159
160 // DataSources returns all of the available data sources that this
161 // provider implements.
162 DataSources() []DataSource
163
164 // ReadDataDiff produces a diff that represents the state that will
165 // be produced when the given data source is read using a later call
166 // to ReadDataApply.
167 ReadDataDiff(*InstanceInfo, *ResourceConfig) (*InstanceDiff, error)
168
169 // ReadDataApply initializes a data instance using the configuration
170 // in a diff produced by ReadDataDiff.
171 ReadDataApply(*InstanceInfo, *InstanceDiff) (*InstanceState, error)
172 }
173
174 // ResourceProviderCloser is an interface that providers that can close
175 // connections that aren't needed anymore must implement.
176 type ResourceProviderCloser interface {
177 Close() error
178 }
179
180 // ResourceType is a type of resource that a resource provider can manage.
181 type ResourceType struct {
182 Name string // Name of the resource, example "instance" (no provider prefix)
183 Importable bool // Whether this resource supports importing
184
185 // SchemaAvailable is set if the provider supports the ProviderSchema,
186 // ResourceTypeSchema and DataSourceSchema methods. Although it is
187 // included on each resource type, it's actually a provider-wide setting
188 // that's smuggled here only because that avoids a breaking change to
189 // the plugin protocol.
190 SchemaAvailable bool
191 }
192
193 // DataSource is a data source that a resource provider implements.
194 type DataSource struct {
195 Name string
196
197 // SchemaAvailable is set if the provider supports the ProviderSchema,
198 // ResourceTypeSchema and DataSourceSchema methods. Although it is
199 // included on each resource type, it's actually a provider-wide setting
200 // that's smuggled here only because that avoids a breaking change to
201 // the plugin protocol.
202 SchemaAvailable bool
203 }
204
205 // ResourceProviderResolver is an interface implemented by objects that are
206 // able to resolve a given set of resource provider version constraints
207 // into ResourceProviderFactory callbacks.
208 type ResourceProviderResolver interface {
209 // Given a constraint map, return a ResourceProviderFactory for each
210 // requested provider. If some or all of the constraints cannot be
211 // satisfied, return a non-nil slice of errors describing the problems.
212 ResolveProviders(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error)
213 }
214
215 // ResourceProviderResolverFunc wraps a callback function and turns it into
216 // a ResourceProviderResolver implementation, for convenience in situations
217 // where a function and its associated closure are sufficient as a resolver
218 // implementation.
219 type ResourceProviderResolverFunc func(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error)
220
221 // ResolveProviders implements ResourceProviderResolver by calling the
222 // wrapped function.
223 func (f ResourceProviderResolverFunc) ResolveProviders(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error) {
224 return f(reqd)
225 }
226
227 // ResourceProviderResolverFixed returns a ResourceProviderResolver that
228 // has a fixed set of provider factories provided by the caller. The returned
229 // resolver ignores version constraints entirely and just returns the given
230 // factory for each requested provider name.
231 //
232 // This function is primarily used in tests, to provide mock providers or
233 // in-process providers under test.
234 func ResourceProviderResolverFixed(factories map[string]ResourceProviderFactory) ResourceProviderResolver {
235 return ResourceProviderResolverFunc(func(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error) {
236 ret := make(map[string]ResourceProviderFactory, len(reqd))
237 var errs []error
238 for name := range reqd {
239 if factory, exists := factories[name]; exists {
240 ret[name] = factory
241 } else {
242 errs = append(errs, fmt.Errorf("provider %q is not available", name))
243 }
244 }
245 return ret, errs
246 })
247 }
248
249 // ResourceProviderFactory is a function type that creates a new instance
250 // of a resource provider.
251 type ResourceProviderFactory func() (ResourceProvider, error)
252
253 // ResourceProviderFactoryFixed is a helper that creates a
254 // ResourceProviderFactory that just returns some fixed provider.
255 func ResourceProviderFactoryFixed(p ResourceProvider) ResourceProviderFactory {
256 return func() (ResourceProvider, error) {
257 return p, nil
258 }
259 }
260
261 func ProviderHasResource(p ResourceProvider, n string) bool {
262 for _, rt := range p.Resources() {
263 if rt.Name == n {
264 return true
265 }
266 }
267
268 return false
269 }
270
271 func ProviderHasDataSource(p ResourceProvider, n string) bool {
272 for _, rt := range p.DataSources() {
273 if rt.Name == n {
274 return true
275 }
276 }
277
278 return false
279 }
280
281 // resourceProviderFactories matches available plugins to the given version
282 // requirements to produce a map of compatible provider plugins if possible,
283 // or an error if the currently-available plugins are insufficient.
284 //
285 // This should be called only with configurations that have passed calls
286 // to config.Validate(), which ensures that all of the given version
287 // constraints are valid. It will panic if any invalid constraints are present.
288 func resourceProviderFactories(resolver providers.Resolver, reqd discovery.PluginRequirements) (map[string]providers.Factory, tfdiags.Diagnostics) {
289 var diags tfdiags.Diagnostics
290 ret, errs := resolver.ResolveProviders(reqd)
291 if errs != nil {
292 diags = diags.Append(
293 tfdiags.Sourceless(tfdiags.Error,
294 "Could not satisfy plugin requirements",
295 errPluginInit,
296 ),
297 )
298
299 for _, err := range errs {
300 diags = diags.Append(err)
301 }
302
303 return nil, diags
304 }
305
306 return ret, nil
307 }
308
309 const errPluginInit = `
310 Plugin reinitialization required. Please run "terraform init".
311
312 Plugins are external binaries that Terraform uses to access and manipulate
313 resources. The configuration provided requires plugins which can't be located,
314 don't satisfy the version constraints, or are otherwise incompatible.
315
316 Terraform automatically discovers provider requirements from your
317 configuration, including providers used in child modules. To see the
318 requirements and constraints from each module, run "terraform providers".
319 `