diff options
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.go | 78 |
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 | ||
3 | import ( | 3 | import ( |
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 | ||
478 | func (s *GRPCProviderServer) ReadResource(_ context.Context, req *proto.ReadResource_Request) (*proto.ReadResource_Response, error) { | 493 | func (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 | } |