aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/helper/schema/schema.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/schema.go75
1 files changed, 67 insertions, 8 deletions
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/schema.go b/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
index 6a3c15a..bcc8e4b 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
@@ -22,7 +22,7 @@ import (
22 "strings" 22 "strings"
23 "sync" 23 "sync"
24 24
25 "github.com/hashicorp/terraform/config" 25 "github.com/hashicorp/terraform/config/hcl2shim"
26 "github.com/hashicorp/terraform/terraform" 26 "github.com/hashicorp/terraform/terraform"
27 "github.com/mitchellh/copystructure" 27 "github.com/mitchellh/copystructure"
28 "github.com/mitchellh/mapstructure" 28 "github.com/mitchellh/mapstructure"
@@ -1365,10 +1365,15 @@ func (m schemaMap) validate(
1365 "%q: this field cannot be set", k)} 1365 "%q: this field cannot be set", k)}
1366 } 1366 }
1367 1367
1368 if raw == config.UnknownVariableValue { 1368 // If the value is unknown then we can't validate it yet.
1369 // If the value is unknown then we can't validate it yet. 1369 // In particular, this avoids spurious type errors where downstream
1370 // In particular, this avoids spurious type errors where downstream 1370 // validation code sees UnknownVariableValue as being just a string.
1371 // validation code sees UnknownVariableValue as being just a string. 1371 // The SDK has to allow the unknown value through initially, so that
1372 // Required fields set via an interpolated value are accepted.
1373 if !isWhollyKnown(raw) {
1374 if schema.Deprecated != "" {
1375 return []string{fmt.Sprintf("%q: [DEPRECATED] %s", k, schema.Deprecated)}, nil
1376 }
1372 return nil, nil 1377 return nil, nil
1373 } 1378 }
1374 1379
@@ -1380,6 +1385,28 @@ func (m schemaMap) validate(
1380 return m.validateType(k, raw, schema, c) 1385 return m.validateType(k, raw, schema, c)
1381} 1386}
1382 1387
1388// isWhollyKnown returns false if the argument contains an UnknownVariableValue
1389func isWhollyKnown(raw interface{}) bool {
1390 switch raw := raw.(type) {
1391 case string:
1392 if raw == hcl2shim.UnknownVariableValue {
1393 return false
1394 }
1395 case []interface{}:
1396 for _, v := range raw {
1397 if !isWhollyKnown(v) {
1398 return false
1399 }
1400 }
1401 case map[string]interface{}:
1402 for _, v := range raw {
1403 if !isWhollyKnown(v) {
1404 return false
1405 }
1406 }
1407 }
1408 return true
1409}
1383func (m schemaMap) validateConflictingAttributes( 1410func (m schemaMap) validateConflictingAttributes(
1384 k string, 1411 k string,
1385 schema *Schema, 1412 schema *Schema,
@@ -1391,7 +1418,7 @@ func (m schemaMap) validateConflictingAttributes(
1391 1418
1392 for _, conflictingKey := range schema.ConflictsWith { 1419 for _, conflictingKey := range schema.ConflictsWith {
1393 if raw, ok := c.Get(conflictingKey); ok { 1420 if raw, ok := c.Get(conflictingKey); ok {
1394 if raw == config.UnknownVariableValue { 1421 if raw == hcl2shim.UnknownVariableValue {
1395 // An unknown value might become unset (null) once known, so 1422 // An unknown value might become unset (null) once known, so
1396 // we must defer validation until it's known. 1423 // we must defer validation until it's known.
1397 continue 1424 continue
@@ -1411,11 +1438,16 @@ func (m schemaMap) validateList(
1411 c *terraform.ResourceConfig) ([]string, []error) { 1438 c *terraform.ResourceConfig) ([]string, []error) {
1412 // first check if the list is wholly unknown 1439 // first check if the list is wholly unknown
1413 if s, ok := raw.(string); ok { 1440 if s, ok := raw.(string); ok {
1414 if s == config.UnknownVariableValue { 1441 if s == hcl2shim.UnknownVariableValue {
1415 return nil, nil 1442 return nil, nil
1416 } 1443 }
1417 } 1444 }
1418 1445
1446 // schemaMap can't validate nil
1447 if raw == nil {
1448 return nil, nil
1449 }
1450
1419 // We use reflection to verify the slice because you can't 1451 // We use reflection to verify the slice because you can't
1420 // case to []interface{} unless the slice is exactly that type. 1452 // case to []interface{} unless the slice is exactly that type.
1421 rawV := reflect.ValueOf(raw) 1453 rawV := reflect.ValueOf(raw)
@@ -1432,6 +1464,15 @@ func (m schemaMap) validateList(
1432 "%s: should be a list", k)} 1464 "%s: should be a list", k)}
1433 } 1465 }
1434 1466
1467 // We can't validate list length if this came from a dynamic block.
1468 // Since there's no way to determine if something was from a dynamic block
1469 // at this point, we're going to skip validation in the new protocol if
1470 // there are any unknowns. Validate will eventually be called again once
1471 // all values are known.
1472 if isProto5() && !isWhollyKnown(raw) {
1473 return nil, nil
1474 }
1475
1435 // Validate length 1476 // Validate length
1436 if schema.MaxItems > 0 && rawV.Len() > schema.MaxItems { 1477 if schema.MaxItems > 0 && rawV.Len() > schema.MaxItems {
1437 return nil, []error{fmt.Errorf( 1478 return nil, []error{fmt.Errorf(
@@ -1489,11 +1530,15 @@ func (m schemaMap) validateMap(
1489 c *terraform.ResourceConfig) ([]string, []error) { 1530 c *terraform.ResourceConfig) ([]string, []error) {
1490 // first check if the list is wholly unknown 1531 // first check if the list is wholly unknown
1491 if s, ok := raw.(string); ok { 1532 if s, ok := raw.(string); ok {
1492 if s == config.UnknownVariableValue { 1533 if s == hcl2shim.UnknownVariableValue {
1493 return nil, nil 1534 return nil, nil
1494 } 1535 }
1495 } 1536 }
1496 1537
1538 // schemaMap can't validate nil
1539 if raw == nil {
1540 return nil, nil
1541 }
1497 // We use reflection to verify the slice because you can't 1542 // We use reflection to verify the slice because you can't
1498 // case to []interface{} unless the slice is exactly that type. 1543 // case to []interface{} unless the slice is exactly that type.
1499 rawV := reflect.ValueOf(raw) 1544 rawV := reflect.ValueOf(raw)
@@ -1620,6 +1665,12 @@ func (m schemaMap) validateObject(
1620 schema map[string]*Schema, 1665 schema map[string]*Schema,
1621 c *terraform.ResourceConfig) ([]string, []error) { 1666 c *terraform.ResourceConfig) ([]string, []error) {
1622 raw, _ := c.Get(k) 1667 raw, _ := c.Get(k)
1668
1669 // schemaMap can't validate nil
1670 if raw == nil {
1671 return nil, nil
1672 }
1673
1623 if _, ok := raw.(map[string]interface{}); !ok && !c.IsComputed(k) { 1674 if _, ok := raw.(map[string]interface{}); !ok && !c.IsComputed(k) {
1624 return nil, []error{fmt.Errorf( 1675 return nil, []error{fmt.Errorf(
1625 "%s: expected object, got %s", 1676 "%s: expected object, got %s",
@@ -1664,6 +1715,14 @@ func (m schemaMap) validatePrimitive(
1664 raw interface{}, 1715 raw interface{},
1665 schema *Schema, 1716 schema *Schema,
1666 c *terraform.ResourceConfig) ([]string, []error) { 1717 c *terraform.ResourceConfig) ([]string, []error) {
1718
1719 // a nil value shouldn't happen in the old protocol, and in the new
1720 // protocol the types have already been validated. Either way, we can't
1721 // reflect on nil, so don't panic.
1722 if raw == nil {
1723 return nil, nil
1724 }
1725
1667 // Catch if the user gave a complex type where a primitive was 1726 // Catch if the user gave a complex type where a primitive was
1668 // expected, so we can return a friendly error message that 1727 // expected, so we can return a friendly error message that
1669 // doesn't contain Go type system terminology. 1728 // doesn't contain Go type system terminology.