aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/helper/plugin/grpc_provider.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/plugin/grpc_provider.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/plugin/grpc_provider.go78
1 files changed, 69 insertions, 9 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/plugin/grpc_provider.go b/vendor/github.com/hashicorp/terraform/helper/plugin/grpc_provider.go
index 510f47f..104c8f5 100644
--- a/vendor/github.com/hashicorp/terraform/helper/plugin/grpc_provider.go
+++ b/vendor/github.com/hashicorp/terraform/helper/plugin/grpc_provider.go
@@ -2,7 +2,6 @@ package plugin
2 2
3import ( 3import (
4 "encoding/json" 4 "encoding/json"
5 "errors"
6 "fmt" 5 "fmt"
7 "log" 6 "log"
8 "strconv" 7 "strconv"
@@ -16,6 +15,7 @@ import (
16 "github.com/hashicorp/terraform/configs/configschema" 15 "github.com/hashicorp/terraform/configs/configschema"
17 "github.com/hashicorp/terraform/helper/schema" 16 "github.com/hashicorp/terraform/helper/schema"
18 proto "github.com/hashicorp/terraform/internal/tfplugin5" 17 proto "github.com/hashicorp/terraform/internal/tfplugin5"
18 "github.com/hashicorp/terraform/plans/objchange"
19 "github.com/hashicorp/terraform/plugin/convert" 19 "github.com/hashicorp/terraform/plugin/convert"
20 "github.com/hashicorp/terraform/terraform" 20 "github.com/hashicorp/terraform/terraform"
21) 21)
@@ -284,6 +284,17 @@ func (s *GRPCProviderServer) UpgradeResourceState(_ context.Context, req *proto.
284 return resp, nil 284 return resp, nil
285 } 285 }
286 286
287 // Now we need to make sure blocks are represented correctly, which means
288 // that missing blocks are empty collections, rather than null.
289 // First we need to CoerceValue to ensure that all object types match.
290 val, err = schemaBlock.CoerceValue(val)
291 if err != nil {
292 resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
293 return resp, nil
294 }
295 // Normalize the value and fill in any missing blocks.
296 val = objchange.NormalizeObjectFromLegacySDK(val, schemaBlock)
297
287 // encode the final state to the expected msgpack format 298 // encode the final state to the expected msgpack format
288 newStateMP, err := msgpack.Marshal(val, schemaBlock.ImpliedType()) 299 newStateMP, err := msgpack.Marshal(val, schemaBlock.ImpliedType())
289 if err != nil { 300 if err != nil {
@@ -316,11 +327,15 @@ func (s *GRPCProviderServer) upgradeFlatmapState(version int, m map[string]strin
316 requiresMigrate = version < res.StateUpgraders[0].Version 327 requiresMigrate = version < res.StateUpgraders[0].Version
317 } 328 }
318 329
319 if requiresMigrate { 330 if requiresMigrate && res.MigrateState == nil {
320 if res.MigrateState == nil { 331 // Providers were previously allowed to bump the version
321 return nil, 0, errors.New("cannot upgrade state, missing MigrateState function") 332 // without declaring MigrateState.
333 // If there are further upgraders, then we've only updated that far.
334 if len(res.StateUpgraders) > 0 {
335 schemaType = res.StateUpgraders[0].Type
336 upgradedVersion = res.StateUpgraders[0].Version
322 } 337 }
323 338 } else if requiresMigrate {
324 is := &terraform.InstanceState{ 339 is := &terraform.InstanceState{
325 ID: m["id"], 340 ID: m["id"],
326 Attributes: m, 341 Attributes: m,
@@ -476,7 +491,12 @@ func (s *GRPCProviderServer) Configure(_ context.Context, req *proto.Configure_R
476} 491}
477 492
478func (s *GRPCProviderServer) ReadResource(_ context.Context, req *proto.ReadResource_Request) (*proto.ReadResource_Response, error) { 493func (s *GRPCProviderServer) ReadResource(_ context.Context, req *proto.ReadResource_Request) (*proto.ReadResource_Response, error) {
479 resp := &proto.ReadResource_Response{} 494 resp := &proto.ReadResource_Response{
495 // helper/schema did previously handle private data during refresh, but
496 // core is now going to expect this to be maintained in order to
497 // persist it in the state.
498 Private: req.Private,
499 }
480 500
481 res := s.provider.ResourcesMap[req.TypeName] 501 res := s.provider.ResourcesMap[req.TypeName]
482 schemaBlock := s.getResourceSchemaBlock(req.TypeName) 502 schemaBlock := s.getResourceSchemaBlock(req.TypeName)
@@ -493,6 +513,15 @@ func (s *GRPCProviderServer) ReadResource(_ context.Context, req *proto.ReadReso
493 return resp, nil 513 return resp, nil
494 } 514 }
495 515
516 private := make(map[string]interface{})
517 if len(req.Private) > 0 {
518 if err := json.Unmarshal(req.Private, &private); err != nil {
519 resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
520 return resp, nil
521 }
522 }
523 instanceState.Meta = private
524
496 newInstanceState, err := res.RefreshWithoutUpgrade(instanceState, s.provider.Meta()) 525 newInstanceState, err := res.RefreshWithoutUpgrade(instanceState, s.provider.Meta())
497 if err != nil { 526 if err != nil {
498 resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err) 527 resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
@@ -569,6 +598,7 @@ func (s *GRPCProviderServer) PlanResourceChange(_ context.Context, req *proto.Pl
569 // We don't usually plan destroys, but this can return early in any case. 598 // We don't usually plan destroys, but this can return early in any case.
570 if proposedNewStateVal.IsNull() { 599 if proposedNewStateVal.IsNull() {
571 resp.PlannedState = req.ProposedNewState 600 resp.PlannedState = req.ProposedNewState
601 resp.PlannedPrivate = req.PriorPrivate
572 return resp, nil 602 return resp, nil
573 } 603 }
574 604
@@ -623,6 +653,7 @@ func (s *GRPCProviderServer) PlanResourceChange(_ context.Context, req *proto.Pl
623 // description that _shows_ there are no changes. This is always the 653 // description that _shows_ there are no changes. This is always the
624 // prior state, because we force a diff above if this is a new instance. 654 // prior state, because we force a diff above if this is a new instance.
625 resp.PlannedState = req.PriorState 655 resp.PlannedState = req.PriorState
656 resp.PlannedPrivate = req.PriorPrivate
626 return resp, nil 657 return resp, nil
627 } 658 }
628 659
@@ -683,6 +714,18 @@ func (s *GRPCProviderServer) PlanResourceChange(_ context.Context, req *proto.Pl
683 Msgpack: plannedMP, 714 Msgpack: plannedMP,
684 } 715 }
685 716
717 // encode any timeouts into the diff Meta
718 t := &schema.ResourceTimeout{}
719 if err := t.ConfigDecode(res, cfg); err != nil {
720 resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
721 return resp, nil
722 }
723
724 if err := t.DiffEncode(diff); err != nil {
725 resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
726 return resp, nil
727 }
728
686 // Now we need to store any NewExtra values, which are where any actual 729 // Now we need to store any NewExtra values, which are where any actual
687 // StateFunc modified config fields are hidden. 730 // StateFunc modified config fields are hidden.
688 privateMap := diff.Meta 731 privateMap := diff.Meta
@@ -929,6 +972,9 @@ func (s *GRPCProviderServer) ImportResourceState(_ context.Context, req *proto.I
929 return resp, nil 972 return resp, nil
930 } 973 }
931 974
975 // Normalize the value and fill in any missing blocks.
976 newStateVal = objchange.NormalizeObjectFromLegacySDK(newStateVal, schemaBlock)
977
932 newStateMP, err := msgpack.Marshal(newStateVal, schemaBlock.ImpliedType()) 978 newStateMP, err := msgpack.Marshal(newStateVal, schemaBlock.ImpliedType())
933 if err != nil { 979 if err != nil {
934 resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err) 980 resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)
@@ -1160,6 +1206,8 @@ func normalizeNullValues(dst, src cty.Value, apply bool) cty.Value {
1160 } 1206 }
1161 } 1207 }
1162 1208
1209 // check the invariants that we need below, to ensure we are working with
1210 // non-null and known values.
1163 if src.IsNull() || !src.IsKnown() || !dst.IsKnown() { 1211 if src.IsNull() || !src.IsKnown() || !dst.IsKnown() {
1164 return dst 1212 return dst
1165 } 1213 }
@@ -1278,8 +1326,12 @@ func normalizeNullValues(dst, src cty.Value, apply bool) cty.Value {
1278 return cty.ListVal(dsts) 1326 return cty.ListVal(dsts)
1279 } 1327 }
1280 1328
1281 case ty.IsPrimitiveType(): 1329 case ty == cty.String:
1282 if dst.IsNull() && src.IsWhollyKnown() && apply { 1330 // The legacy SDK should not be able to remove a value during plan or
1331 // apply, however we are only going to overwrite this if the source was
1332 // an empty string, since that is what is often equated with unset and
1333 // lost in the diff process.
1334 if dst.IsNull() && src.AsString() == "" {
1283 return src 1335 return src
1284 } 1336 }
1285 } 1337 }
@@ -1305,11 +1357,19 @@ func validateConfigNulls(v cty.Value, path cty.Path) []*proto.Diagnostic {
1305 for it.Next() { 1357 for it.Next() {
1306 kv, ev := it.Element() 1358 kv, ev := it.Element()
1307 if ev.IsNull() { 1359 if ev.IsNull() {
1360 // if this is a set, the kv is also going to be null which
1361 // isn't a valid path element, so we can't append it to the
1362 // diagnostic.
1363 p := path
1364 if !kv.IsNull() {
1365 p = append(p, cty.IndexStep{Key: kv})
1366 }
1367
1308 diags = append(diags, &proto.Diagnostic{ 1368 diags = append(diags, &proto.Diagnostic{
1309 Severity: proto.Diagnostic_ERROR, 1369 Severity: proto.Diagnostic_ERROR,
1310 Summary: "Null value found in list", 1370 Summary: "Null value found in list",
1311 Detail: "Null values are not allowed for this attribute value.", 1371 Detail: "Null values are not allowed for this attribute value.",
1312 Attribute: convert.PathToAttributePath(append(path, cty.IndexStep{Key: kv})), 1372 Attribute: convert.PathToAttributePath(p),
1313 }) 1373 })
1314 continue 1374 continue
1315 } 1375 }