diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/plugin/grpc_provider.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/plugin/grpc_provider.go | 562 |
1 files changed, 562 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/plugin/grpc_provider.go b/vendor/github.com/hashicorp/terraform/plugin/grpc_provider.go new file mode 100644 index 0000000..ae9a400 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/plugin/grpc_provider.go | |||
@@ -0,0 +1,562 @@ | |||
1 | package plugin | ||
2 | |||
3 | import ( | ||
4 | "context" | ||
5 | "errors" | ||
6 | "log" | ||
7 | "sync" | ||
8 | |||
9 | "github.com/zclconf/go-cty/cty" | ||
10 | |||
11 | plugin "github.com/hashicorp/go-plugin" | ||
12 | proto "github.com/hashicorp/terraform/internal/tfplugin5" | ||
13 | "github.com/hashicorp/terraform/plugin/convert" | ||
14 | "github.com/hashicorp/terraform/providers" | ||
15 | "github.com/hashicorp/terraform/version" | ||
16 | "github.com/zclconf/go-cty/cty/msgpack" | ||
17 | "google.golang.org/grpc" | ||
18 | ) | ||
19 | |||
20 | // GRPCProviderPlugin implements plugin.GRPCPlugin for the go-plugin package. | ||
21 | type GRPCProviderPlugin struct { | ||
22 | plugin.Plugin | ||
23 | GRPCProvider func() proto.ProviderServer | ||
24 | } | ||
25 | |||
26 | func (p *GRPCProviderPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) { | ||
27 | return &GRPCProvider{ | ||
28 | client: proto.NewProviderClient(c), | ||
29 | ctx: ctx, | ||
30 | }, nil | ||
31 | } | ||
32 | |||
33 | func (p *GRPCProviderPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error { | ||
34 | proto.RegisterProviderServer(s, p.GRPCProvider()) | ||
35 | return nil | ||
36 | } | ||
37 | |||
38 | // GRPCProvider handles the client, or core side of the plugin rpc connection. | ||
39 | // The GRPCProvider methods are mostly a translation layer between the | ||
40 | // terraform provioders types and the grpc proto types, directly converting | ||
41 | // between the two. | ||
42 | type GRPCProvider struct { | ||
43 | // PluginClient provides a reference to the plugin.Client which controls the plugin process. | ||
44 | // This allows the GRPCProvider a way to shutdown the plugin process. | ||
45 | PluginClient *plugin.Client | ||
46 | |||
47 | // TestServer contains a grpc.Server to close when the GRPCProvider is being | ||
48 | // used in an end to end test of a provider. | ||
49 | TestServer *grpc.Server | ||
50 | |||
51 | // Proto client use to make the grpc service calls. | ||
52 | client proto.ProviderClient | ||
53 | |||
54 | // this context is created by the plugin package, and is canceled when the | ||
55 | // plugin process ends. | ||
56 | ctx context.Context | ||
57 | |||
58 | // schema stores the schema for this provider. This is used to properly | ||
59 | // serialize the state for requests. | ||
60 | mu sync.Mutex | ||
61 | schemas providers.GetSchemaResponse | ||
62 | } | ||
63 | |||
64 | // getSchema is used internally to get the saved provider schema. The schema | ||
65 | // should have already been fetched from the provider, but we have to | ||
66 | // synchronize access to avoid being called concurrently with GetSchema. | ||
67 | func (p *GRPCProvider) getSchema() providers.GetSchemaResponse { | ||
68 | p.mu.Lock() | ||
69 | // unlock inline in case GetSchema needs to be called | ||
70 | if p.schemas.Provider.Block != nil { | ||
71 | p.mu.Unlock() | ||
72 | return p.schemas | ||
73 | } | ||
74 | p.mu.Unlock() | ||
75 | |||
76 | // the schema should have been fetched already, but give it another shot | ||
77 | // just in case things are being called out of order. This may happen for | ||
78 | // tests. | ||
79 | schemas := p.GetSchema() | ||
80 | if schemas.Diagnostics.HasErrors() { | ||
81 | panic(schemas.Diagnostics.Err()) | ||
82 | } | ||
83 | |||
84 | return schemas | ||
85 | } | ||
86 | |||
87 | // getResourceSchema is a helper to extract the schema for a resource, and | ||
88 | // panics if the schema is not available. | ||
89 | func (p *GRPCProvider) getResourceSchema(name string) providers.Schema { | ||
90 | schema := p.getSchema() | ||
91 | resSchema, ok := schema.ResourceTypes[name] | ||
92 | if !ok { | ||
93 | panic("unknown resource type " + name) | ||
94 | } | ||
95 | return resSchema | ||
96 | } | ||
97 | |||
98 | // gettDatasourceSchema is a helper to extract the schema for a datasource, and | ||
99 | // panics if that schema is not available. | ||
100 | func (p *GRPCProvider) getDatasourceSchema(name string) providers.Schema { | ||
101 | schema := p.getSchema() | ||
102 | dataSchema, ok := schema.DataSources[name] | ||
103 | if !ok { | ||
104 | panic("unknown data source " + name) | ||
105 | } | ||
106 | return dataSchema | ||
107 | } | ||
108 | |||
109 | func (p *GRPCProvider) GetSchema() (resp providers.GetSchemaResponse) { | ||
110 | log.Printf("[TRACE] GRPCProvider: GetSchema") | ||
111 | p.mu.Lock() | ||
112 | defer p.mu.Unlock() | ||
113 | |||
114 | if p.schemas.Provider.Block != nil { | ||
115 | return p.schemas | ||
116 | } | ||
117 | |||
118 | resp.ResourceTypes = make(map[string]providers.Schema) | ||
119 | resp.DataSources = make(map[string]providers.Schema) | ||
120 | |||
121 | // Some providers may generate quite large schemas, and the internal default | ||
122 | // grpc response size limit is 4MB. 64MB should cover most any use case, and | ||
123 | // if we get providers nearing that we may want to consider a finer-grained | ||
124 | // API to fetch individual resource schemas. | ||
125 | // Note: this option is marked as EXPERIMENTAL in the grpc API. | ||
126 | const maxRecvSize = 64 << 20 | ||
127 | protoResp, err := p.client.GetSchema(p.ctx, new(proto.GetProviderSchema_Request), grpc.MaxRecvMsgSizeCallOption{MaxRecvMsgSize: maxRecvSize}) | ||
128 | if err != nil { | ||
129 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
130 | return resp | ||
131 | } | ||
132 | |||
133 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
134 | |||
135 | if protoResp.Provider == nil { | ||
136 | resp.Diagnostics = resp.Diagnostics.Append(errors.New("missing provider schema")) | ||
137 | return resp | ||
138 | } | ||
139 | |||
140 | resp.Provider = convert.ProtoToProviderSchema(protoResp.Provider) | ||
141 | |||
142 | for name, res := range protoResp.ResourceSchemas { | ||
143 | resp.ResourceTypes[name] = convert.ProtoToProviderSchema(res) | ||
144 | } | ||
145 | |||
146 | for name, data := range protoResp.DataSourceSchemas { | ||
147 | resp.DataSources[name] = convert.ProtoToProviderSchema(data) | ||
148 | } | ||
149 | |||
150 | p.schemas = resp | ||
151 | |||
152 | return resp | ||
153 | } | ||
154 | |||
155 | func (p *GRPCProvider) PrepareProviderConfig(r providers.PrepareProviderConfigRequest) (resp providers.PrepareProviderConfigResponse) { | ||
156 | log.Printf("[TRACE] GRPCProvider: PrepareProviderConfig") | ||
157 | |||
158 | schema := p.getSchema() | ||
159 | ty := schema.Provider.Block.ImpliedType() | ||
160 | |||
161 | mp, err := msgpack.Marshal(r.Config, ty) | ||
162 | if err != nil { | ||
163 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
164 | return resp | ||
165 | } | ||
166 | |||
167 | protoReq := &proto.PrepareProviderConfig_Request{ | ||
168 | Config: &proto.DynamicValue{Msgpack: mp}, | ||
169 | } | ||
170 | |||
171 | protoResp, err := p.client.PrepareProviderConfig(p.ctx, protoReq) | ||
172 | if err != nil { | ||
173 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
174 | return resp | ||
175 | } | ||
176 | |||
177 | config := cty.NullVal(ty) | ||
178 | if protoResp.PreparedConfig != nil { | ||
179 | config, err = msgpack.Unmarshal(protoResp.PreparedConfig.Msgpack, ty) | ||
180 | if err != nil { | ||
181 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
182 | return resp | ||
183 | } | ||
184 | } | ||
185 | resp.PreparedConfig = config | ||
186 | |||
187 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
188 | return resp | ||
189 | } | ||
190 | |||
191 | func (p *GRPCProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTypeConfigRequest) (resp providers.ValidateResourceTypeConfigResponse) { | ||
192 | log.Printf("[TRACE] GRPCProvider: ValidateResourceTypeConfig") | ||
193 | resourceSchema := p.getResourceSchema(r.TypeName) | ||
194 | |||
195 | mp, err := msgpack.Marshal(r.Config, resourceSchema.Block.ImpliedType()) | ||
196 | if err != nil { | ||
197 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
198 | return resp | ||
199 | } | ||
200 | |||
201 | protoReq := &proto.ValidateResourceTypeConfig_Request{ | ||
202 | TypeName: r.TypeName, | ||
203 | Config: &proto.DynamicValue{Msgpack: mp}, | ||
204 | } | ||
205 | |||
206 | protoResp, err := p.client.ValidateResourceTypeConfig(p.ctx, protoReq) | ||
207 | if err != nil { | ||
208 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
209 | return resp | ||
210 | } | ||
211 | |||
212 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
213 | return resp | ||
214 | } | ||
215 | |||
216 | func (p *GRPCProvider) ValidateDataSourceConfig(r providers.ValidateDataSourceConfigRequest) (resp providers.ValidateDataSourceConfigResponse) { | ||
217 | log.Printf("[TRACE] GRPCProvider: ValidateDataSourceConfig") | ||
218 | |||
219 | dataSchema := p.getDatasourceSchema(r.TypeName) | ||
220 | |||
221 | mp, err := msgpack.Marshal(r.Config, dataSchema.Block.ImpliedType()) | ||
222 | if err != nil { | ||
223 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
224 | return resp | ||
225 | } | ||
226 | |||
227 | protoReq := &proto.ValidateDataSourceConfig_Request{ | ||
228 | TypeName: r.TypeName, | ||
229 | Config: &proto.DynamicValue{Msgpack: mp}, | ||
230 | } | ||
231 | |||
232 | protoResp, err := p.client.ValidateDataSourceConfig(p.ctx, protoReq) | ||
233 | if err != nil { | ||
234 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
235 | return resp | ||
236 | } | ||
237 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
238 | return resp | ||
239 | } | ||
240 | |||
241 | func (p *GRPCProvider) UpgradeResourceState(r providers.UpgradeResourceStateRequest) (resp providers.UpgradeResourceStateResponse) { | ||
242 | log.Printf("[TRACE] GRPCProvider: UpgradeResourceState") | ||
243 | |||
244 | resSchema := p.getResourceSchema(r.TypeName) | ||
245 | |||
246 | protoReq := &proto.UpgradeResourceState_Request{ | ||
247 | TypeName: r.TypeName, | ||
248 | Version: int64(r.Version), | ||
249 | RawState: &proto.RawState{ | ||
250 | Json: r.RawStateJSON, | ||
251 | Flatmap: r.RawStateFlatmap, | ||
252 | }, | ||
253 | } | ||
254 | |||
255 | protoResp, err := p.client.UpgradeResourceState(p.ctx, protoReq) | ||
256 | if err != nil { | ||
257 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
258 | return resp | ||
259 | } | ||
260 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
261 | |||
262 | state := cty.NullVal(resSchema.Block.ImpliedType()) | ||
263 | if protoResp.UpgradedState != nil { | ||
264 | state, err = msgpack.Unmarshal(protoResp.UpgradedState.Msgpack, resSchema.Block.ImpliedType()) | ||
265 | if err != nil { | ||
266 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
267 | return resp | ||
268 | } | ||
269 | } | ||
270 | |||
271 | resp.UpgradedState = state | ||
272 | return resp | ||
273 | } | ||
274 | |||
275 | func (p *GRPCProvider) Configure(r providers.ConfigureRequest) (resp providers.ConfigureResponse) { | ||
276 | log.Printf("[TRACE] GRPCProvider: Configure") | ||
277 | |||
278 | schema := p.getSchema() | ||
279 | |||
280 | var mp []byte | ||
281 | |||
282 | // we don't have anything to marshal if there's no config | ||
283 | mp, err := msgpack.Marshal(r.Config, schema.Provider.Block.ImpliedType()) | ||
284 | if err != nil { | ||
285 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
286 | return resp | ||
287 | } | ||
288 | |||
289 | protoReq := &proto.Configure_Request{ | ||
290 | TerraformVersion: version.Version, | ||
291 | Config: &proto.DynamicValue{ | ||
292 | Msgpack: mp, | ||
293 | }, | ||
294 | } | ||
295 | |||
296 | protoResp, err := p.client.Configure(p.ctx, protoReq) | ||
297 | if err != nil { | ||
298 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
299 | return resp | ||
300 | } | ||
301 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
302 | return resp | ||
303 | } | ||
304 | |||
305 | func (p *GRPCProvider) Stop() error { | ||
306 | log.Printf("[TRACE] GRPCProvider: Stop") | ||
307 | |||
308 | resp, err := p.client.Stop(p.ctx, new(proto.Stop_Request)) | ||
309 | if err != nil { | ||
310 | return err | ||
311 | } | ||
312 | |||
313 | if resp.Error != "" { | ||
314 | return errors.New(resp.Error) | ||
315 | } | ||
316 | return nil | ||
317 | } | ||
318 | |||
319 | func (p *GRPCProvider) ReadResource(r providers.ReadResourceRequest) (resp providers.ReadResourceResponse) { | ||
320 | log.Printf("[TRACE] GRPCProvider: ReadResource") | ||
321 | |||
322 | resSchema := p.getResourceSchema(r.TypeName) | ||
323 | |||
324 | mp, err := msgpack.Marshal(r.PriorState, resSchema.Block.ImpliedType()) | ||
325 | if err != nil { | ||
326 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
327 | return resp | ||
328 | } | ||
329 | |||
330 | protoReq := &proto.ReadResource_Request{ | ||
331 | TypeName: r.TypeName, | ||
332 | CurrentState: &proto.DynamicValue{Msgpack: mp}, | ||
333 | } | ||
334 | |||
335 | protoResp, err := p.client.ReadResource(p.ctx, protoReq) | ||
336 | if err != nil { | ||
337 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
338 | return resp | ||
339 | } | ||
340 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
341 | |||
342 | state := cty.NullVal(resSchema.Block.ImpliedType()) | ||
343 | if protoResp.NewState != nil { | ||
344 | state, err = msgpack.Unmarshal(protoResp.NewState.Msgpack, resSchema.Block.ImpliedType()) | ||
345 | if err != nil { | ||
346 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
347 | return resp | ||
348 | } | ||
349 | } | ||
350 | resp.NewState = state | ||
351 | |||
352 | return resp | ||
353 | } | ||
354 | |||
355 | func (p *GRPCProvider) PlanResourceChange(r providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) { | ||
356 | log.Printf("[TRACE] GRPCProvider: PlanResourceChange") | ||
357 | |||
358 | resSchema := p.getResourceSchema(r.TypeName) | ||
359 | |||
360 | priorMP, err := msgpack.Marshal(r.PriorState, resSchema.Block.ImpliedType()) | ||
361 | if err != nil { | ||
362 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
363 | return resp | ||
364 | } | ||
365 | |||
366 | configMP, err := msgpack.Marshal(r.Config, resSchema.Block.ImpliedType()) | ||
367 | if err != nil { | ||
368 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
369 | return resp | ||
370 | } | ||
371 | |||
372 | propMP, err := msgpack.Marshal(r.ProposedNewState, resSchema.Block.ImpliedType()) | ||
373 | if err != nil { | ||
374 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
375 | return resp | ||
376 | } | ||
377 | |||
378 | protoReq := &proto.PlanResourceChange_Request{ | ||
379 | TypeName: r.TypeName, | ||
380 | PriorState: &proto.DynamicValue{Msgpack: priorMP}, | ||
381 | Config: &proto.DynamicValue{Msgpack: configMP}, | ||
382 | ProposedNewState: &proto.DynamicValue{Msgpack: propMP}, | ||
383 | PriorPrivate: r.PriorPrivate, | ||
384 | } | ||
385 | |||
386 | protoResp, err := p.client.PlanResourceChange(p.ctx, protoReq) | ||
387 | if err != nil { | ||
388 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
389 | return resp | ||
390 | } | ||
391 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
392 | |||
393 | state := cty.NullVal(resSchema.Block.ImpliedType()) | ||
394 | if protoResp.PlannedState != nil { | ||
395 | state, err = msgpack.Unmarshal(protoResp.PlannedState.Msgpack, resSchema.Block.ImpliedType()) | ||
396 | if err != nil { | ||
397 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
398 | return resp | ||
399 | } | ||
400 | } | ||
401 | resp.PlannedState = state | ||
402 | |||
403 | for _, p := range protoResp.RequiresReplace { | ||
404 | resp.RequiresReplace = append(resp.RequiresReplace, convert.AttributePathToPath(p)) | ||
405 | } | ||
406 | |||
407 | resp.PlannedPrivate = protoResp.PlannedPrivate | ||
408 | |||
409 | resp.LegacyTypeSystem = protoResp.LegacyTypeSystem | ||
410 | |||
411 | return resp | ||
412 | } | ||
413 | |||
414 | func (p *GRPCProvider) ApplyResourceChange(r providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) { | ||
415 | log.Printf("[TRACE] GRPCProvider: ApplyResourceChange") | ||
416 | |||
417 | resSchema := p.getResourceSchema(r.TypeName) | ||
418 | |||
419 | priorMP, err := msgpack.Marshal(r.PriorState, resSchema.Block.ImpliedType()) | ||
420 | if err != nil { | ||
421 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
422 | return resp | ||
423 | } | ||
424 | plannedMP, err := msgpack.Marshal(r.PlannedState, resSchema.Block.ImpliedType()) | ||
425 | if err != nil { | ||
426 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
427 | return resp | ||
428 | } | ||
429 | configMP, err := msgpack.Marshal(r.Config, resSchema.Block.ImpliedType()) | ||
430 | if err != nil { | ||
431 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
432 | return resp | ||
433 | } | ||
434 | |||
435 | protoReq := &proto.ApplyResourceChange_Request{ | ||
436 | TypeName: r.TypeName, | ||
437 | PriorState: &proto.DynamicValue{Msgpack: priorMP}, | ||
438 | PlannedState: &proto.DynamicValue{Msgpack: plannedMP}, | ||
439 | Config: &proto.DynamicValue{Msgpack: configMP}, | ||
440 | PlannedPrivate: r.PlannedPrivate, | ||
441 | } | ||
442 | |||
443 | protoResp, err := p.client.ApplyResourceChange(p.ctx, protoReq) | ||
444 | if err != nil { | ||
445 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
446 | return resp | ||
447 | } | ||
448 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
449 | |||
450 | resp.Private = protoResp.Private | ||
451 | |||
452 | state := cty.NullVal(resSchema.Block.ImpliedType()) | ||
453 | if protoResp.NewState != nil { | ||
454 | state, err = msgpack.Unmarshal(protoResp.NewState.Msgpack, resSchema.Block.ImpliedType()) | ||
455 | if err != nil { | ||
456 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
457 | return resp | ||
458 | } | ||
459 | } | ||
460 | resp.NewState = state | ||
461 | |||
462 | resp.LegacyTypeSystem = protoResp.LegacyTypeSystem | ||
463 | |||
464 | return resp | ||
465 | } | ||
466 | |||
467 | func (p *GRPCProvider) ImportResourceState(r providers.ImportResourceStateRequest) (resp providers.ImportResourceStateResponse) { | ||
468 | log.Printf("[TRACE] GRPCProvider: ImportResourceState") | ||
469 | |||
470 | protoReq := &proto.ImportResourceState_Request{ | ||
471 | TypeName: r.TypeName, | ||
472 | Id: r.ID, | ||
473 | } | ||
474 | |||
475 | protoResp, err := p.client.ImportResourceState(p.ctx, protoReq) | ||
476 | if err != nil { | ||
477 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
478 | return resp | ||
479 | } | ||
480 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
481 | |||
482 | for _, imported := range protoResp.ImportedResources { | ||
483 | resource := providers.ImportedResource{ | ||
484 | TypeName: imported.TypeName, | ||
485 | Private: imported.Private, | ||
486 | } | ||
487 | |||
488 | resSchema := p.getResourceSchema(resource.TypeName) | ||
489 | state := cty.NullVal(resSchema.Block.ImpliedType()) | ||
490 | if imported.State != nil { | ||
491 | state, err = msgpack.Unmarshal(imported.State.Msgpack, resSchema.Block.ImpliedType()) | ||
492 | if err != nil { | ||
493 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
494 | return resp | ||
495 | } | ||
496 | } | ||
497 | resource.State = state | ||
498 | resp.ImportedResources = append(resp.ImportedResources, resource) | ||
499 | } | ||
500 | |||
501 | return resp | ||
502 | } | ||
503 | |||
504 | func (p *GRPCProvider) ReadDataSource(r providers.ReadDataSourceRequest) (resp providers.ReadDataSourceResponse) { | ||
505 | log.Printf("[TRACE] GRPCProvider: ReadDataSource") | ||
506 | |||
507 | dataSchema := p.getDatasourceSchema(r.TypeName) | ||
508 | |||
509 | config, err := msgpack.Marshal(r.Config, dataSchema.Block.ImpliedType()) | ||
510 | if err != nil { | ||
511 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
512 | return resp | ||
513 | } | ||
514 | |||
515 | protoReq := &proto.ReadDataSource_Request{ | ||
516 | TypeName: r.TypeName, | ||
517 | Config: &proto.DynamicValue{ | ||
518 | Msgpack: config, | ||
519 | }, | ||
520 | } | ||
521 | |||
522 | protoResp, err := p.client.ReadDataSource(p.ctx, protoReq) | ||
523 | if err != nil { | ||
524 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
525 | return resp | ||
526 | } | ||
527 | resp.Diagnostics = resp.Diagnostics.Append(convert.ProtoToDiagnostics(protoResp.Diagnostics)) | ||
528 | |||
529 | state := cty.NullVal(dataSchema.Block.ImpliedType()) | ||
530 | if protoResp.State != nil { | ||
531 | state, err = msgpack.Unmarshal(protoResp.State.Msgpack, dataSchema.Block.ImpliedType()) | ||
532 | if err != nil { | ||
533 | resp.Diagnostics = resp.Diagnostics.Append(err) | ||
534 | return resp | ||
535 | } | ||
536 | } | ||
537 | resp.State = state | ||
538 | |||
539 | return resp | ||
540 | } | ||
541 | |||
542 | // closing the grpc connection is final, and terraform will call it at the end of every phase. | ||
543 | func (p *GRPCProvider) Close() error { | ||
544 | log.Printf("[TRACE] GRPCProvider: Close") | ||
545 | |||
546 | // Make sure to stop the server if we're not running within go-plugin. | ||
547 | if p.TestServer != nil { | ||
548 | p.TestServer.Stop() | ||
549 | } | ||
550 | |||
551 | // Check this since it's not automatically inserted during plugin creation. | ||
552 | // It's currently only inserted by the command package, because that is | ||
553 | // where the factory is built and is the only point with access to the | ||
554 | // plugin.Client. | ||
555 | if p.PluginClient == nil { | ||
556 | log.Println("[DEBUG] provider has no plugin.Client") | ||
557 | return nil | ||
558 | } | ||
559 | |||
560 | p.PluginClient.Kill() | ||
561 | return nil | ||
562 | } | ||