Merge pull request #773 from ceh/issue-691

helper/schema: fix panic when validating composite schema type
This commit is contained in:
Mitchell Hashimoto 2015-01-14 09:28:11 -08:00
commit 152e72ffa6
26 changed files with 131 additions and 50 deletions

View File

@ -3,7 +3,7 @@
The count parameter on resources can simplify configurations
and let you scale resources by simply incrementing a number.
Additionally, variables can be used to expand a list of resources
Additionally, variables can be used to expand an array of resources
for use elsewhere.
As with all examples, just copy and paste the example and run

View File

@ -142,7 +142,7 @@ type Schema struct {
// element type is a complex structure, potentially with its own lifecycle.
Elem interface{}
// The follow fields are only valid for a TypeSet type.
// The following fields are only valid for a TypeSet type.
//
// Set defines a function to determine the unique ID of an item so that
// a proper set can be built.
@ -902,7 +902,7 @@ func (m schemaMap) validate(
"%s: this field cannot be set", k)}
}
return m.validatePrimitive(k, raw, schema, c)
return m.validateType(k, raw, schema, c)
}
func (m schemaMap) validateList(
@ -915,7 +915,7 @@ func (m schemaMap) validateList(
rawV := reflect.ValueOf(raw)
if rawV.Kind() != reflect.Slice {
return nil, []error{fmt.Errorf(
"%s: should be a list", k)}
"%s: should be an array", k)}
}
// Now build the []interface{}
@ -936,8 +936,7 @@ func (m schemaMap) validateList(
// This is a sub-resource
ws2, es2 = m.validateObject(key, t.Schema, c)
case *Schema:
// This is some sort of primitive
ws2, es2 = m.validatePrimitive(key, raw, t, c)
ws2, es2 = m.validateType(key, raw, t, c)
}
if len(ws2) > 0 {
@ -1041,12 +1040,6 @@ func (m schemaMap) validatePrimitive(
}
switch schema.Type {
case TypeSet:
fallthrough
case TypeList:
return m.validateList(k, raw, schema, c)
case TypeMap:
return m.validateMap(k, raw, schema, c)
case TypeBool:
// Verify that we can parse this as the correct type
var n bool
@ -1071,3 +1064,20 @@ func (m schemaMap) validatePrimitive(
return nil, nil
}
func (m schemaMap) validateType(
k string,
raw interface{},
schema *Schema,
c *terraform.ResourceConfig) ([]string, []error) {
switch schema.Type {
case TypeSet:
fallthrough
case TypeList:
return m.validateList(k, raw, schema, c)
case TypeMap:
return m.validateMap(k, raw, schema, c)
default:
return m.validatePrimitive(k, raw, schema, c)
}
}

View File

@ -2503,6 +2503,45 @@ func TestSchemaMap_Validate(t *testing.T) {
Err: true,
},
{
Schema: map[string]*Schema{
"security_groups": &Schema{
Type: TypeSet,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &Schema{Type: TypeString},
Set: func(v interface{}) int {
return len(v.(string))
},
},
},
Config: map[string]interface{}{
"security_groups": []interface{}{"${var.foo}"},
},
Err: false,
},
{
Schema: map[string]*Schema{
"security_groups": &Schema{
Type: TypeSet,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &Schema{Type: TypeString},
},
},
Config: map[string]interface{}{
"security_groups": "${var.foo}",
},
Err: true,
},
}
for i, tc := range cases {

View File

@ -4148,6 +4148,22 @@ func TestContextPlan_varMultiCountOne(t *testing.T) {
}
}
func TestContextPlan_varListErr(t *testing.T) {
m := testModule(t, "plan-var-list-err")
p := testProvider("aws")
ctx := testContext(t, &ContextOpts{
Module: m,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
})
_, err := ctx.Plan(nil)
if err == nil {
t.Fatal("should error")
}
}
func TestContextRefresh(t *testing.T) {
p := testProvider("aws")
m := testModule(t, "refresh-basic")

View File

@ -0,0 +1,16 @@
provider "aws" {
access_key = "a"
secret_key = "b"
region = "us-east-1"
}
resource "aws_instance" "foo" {
ami = "ami-foo"
instance_type = "t2.micro"
security_groups = "${aws_security_group.foo.name}"
}
resource "aws_security_group" "foo" {
name = "foobar"
description = "foobar"
}

View File

@ -32,7 +32,7 @@ will interpolate the ID attribute from the "aws\_instance"
resource named "web". If the resource has a `count` attribute set,
you can access individual attributes with a zero-based index, such
as `${aws_instance.web.0.id}`. You can also use the splat syntax
to get a list of all the attributes: `${aws_instance.web.*.id}`.
to get an array of all the attributes: `${aws_instance.web.*.id}`.
This is documented in more detail in the
[resource configuration page](/docs/configuration/resources.html).
@ -68,16 +68,16 @@ The supported built-in functions are:
in this file are _not_ interpolated. The contents of the file are
read as-is.
* `join(delim, list)` - Joins the list with the delimiter. A list is
* `join(delim, array)` - Joins the array with the delimiter. An array is
only possible with splat variables from resources with a count
greater than one. Example: `join(",", aws_instance.foo.*.id)`
* `lookup(map, key)` - Performs a dynamic lookup into a mapping
variable.
* `element(list, index)` - Returns a single element from a list
* `element(array, index)` - Returns a single element from an array
at the given index. If the index is greater than the number of
elements, this function will wrap using a standard mod algorithm.
A list is only possible with splat variables from resources with
An array is only possible with splat variables from resources with
a count greater than one.
Example: `element(aws_subnet.foo.*.id, count.index)`

View File

@ -48,7 +48,7 @@ There are **meta-parameters** available to all resources:
[interpolation](/docs/configuration/interpolation.html) to reference
the current count index in your resource.
* `depends_on` (list of strings) - Explicit dependencies that this
* `depends_on` (array of strings) - Explicit dependencies that this
resource has. These dependencies will be created before this
resource. The dependencies are in the format of `TYPE.NAME`,
for example `aws_instance.web`.

View File

@ -33,17 +33,17 @@ The following arguments are supported:
* `name` - (Required) The name of the auto scale group.
* `max_size` - (Required) The maximum size of the auto scale group.
* `min_size` - (Required) The minimum size of the auto scale group.
* `availability_zones` - (Required) A list of AZs to launch resources in.
* `availability_zones` - (Required) An array of AZs to launch resources in.
* `launch_configuration` - (Required) The ID of the launch configuration to use.
* `health_check_grace_period` - (Optional) Time after instance comes into service before checking health.
* `health_check_type` - (Optional) "EC2" or "ELB". Controls how health checking is done.
* `desired_capacity` - (Optional) The number of Amazon EC2 instances that should be running in the group.
* `force_delete` - (Optional) Allows deleting the autoscaling group without waiting
for all instances in the pool to terminate.
* `load_balancers` (Optional) A list of load balancer names to add to the autoscaling
* `load_balancers` (Optional) An array of load balancer names to add to the autoscaling
group names.
* `vpc_zone_identifier` (Optional) A list of subnet IDs to launch resources in.
* `termination_policies` (Optional) A list of policies to decide how the instances in the auto scale group should be terminated.
* `vpc_zone_identifier` (Optional) An array of subnet IDs to launch resources in.
* `termination_policies` (Optional) An array of policies to decide how the instances in the auto scale group should be terminated.
## Attributes Reference

View File

@ -50,9 +50,9 @@ The following arguments are supported:
* `multi_az` - (Optional) Specifies if the RDS instance is multi-AZ
* `port` - (Optional) The port on which the DB accepts connections.
* `publicly_accessible` - (Optional) Bool to control if instance is publicly accessible.
* `vpc_security_group_ids` - (Optional) List of VPC security groups to associate.
* `vpc_security_group_ids` - (Optional) Array of VPC security groups to associate.
* `skip_final_snapshot` - (Optional) Enables skipping the final snapshot on deletion.
* `security_group_names` - (Optional) List of DB Security Groups to associate.
* `security_group_names` - (Optional) Array of DB Security Groups to associate.
* `db_subnet_group_name` - (Optional) Name of DB subnet group
* `parameter_group_name` - (Optional) Name of the DB parameter group to associate.

View File

@ -35,7 +35,7 @@ The following arguments are supported:
* `name` - (Required) The name of the DB parameter group.
* `family` - (Required) The family of the DB parameter group.
* `description` - (Required) The description of the DB parameter group.
* `parameter` - (Optional) A list of DB parameters to apply.
* `parameter` - (Optional) An array of DB parameters to apply.
Parameter blocks support the following:

View File

@ -29,7 +29,7 @@ The following arguments are supported:
* `name` - (Required) The name of the DB security group.
* `description` - (Required) The description of the DB security group.
* `ingress` - (Optional) A list of ingress rules.
* `ingress` - (Optional) An array of ingress rules.
Ingress blocks support the following:

View File

@ -26,7 +26,7 @@ The following arguments are supported:
* `name` - (Required) The name of the DB security group.
* `description` - (Required) The description of the DB security group.
* `subnet_ids` - (Required) A list of ingress rules.
* `subnet_ids` - (Required) An array of ingress rules.
## Attributes Reference

View File

@ -52,11 +52,11 @@ The following arguments are supported:
* `name` - (Required) The name of the ELB
* `availability_zones` - (Optional) The AZ's to serve traffic in.
* `security_groups` - (Optional) A list of security group IDs to assign to the ELB.
* `subnets` - (Optional) A list of subnets to attach to the ELB.
* `instances` - (Optional) A list of instance ids to place in the ELB pool.
* `security_groups` - (Optional) An array of security group IDs to assign to the ELB.
* `subnets` - (Optional) An array of subnets to attach to the ELB.
* `instances` - (Optional) An array of instance ids to place in the ELB pool.
* `internal` - (Optional) If true, ELB will be an internal ELB.
* `listener` - (Required) A list of listener blocks. Listeners documented below.
* `listener` - (Required) An array of listener blocks. Listeners documented below.
* `health_check` - (Optional) A health_check block. Health Check documented below.
* `cross_zone_load_balancing` - (Optional) Enable cross-zone load balancing.
@ -83,4 +83,4 @@ The following attributes are exported:
* `id` - The name of the ELB
* `name` - The name of the ELB
* `dns_name` - The DNS name of the ELB
* `instances` - The list of instances in the ELB
* `instances` - The array of instances in the ELB

View File

@ -34,7 +34,7 @@ The following arguments are supported:
EBS-optimized.
* `instance_type` - (Required) The type of instance to start
* `key_name` - (Optional) The key name to use for the instance.
* `security_groups` - (Optional) A list of security group IDs or names to associate with.
* `security_groups` - (Optional) An array of security group IDs or names to associate with.
If you are within a non-default VPC, you'll need to use the security group ID. Otherwise,
for EC2 and the default VPC, use the security group name.
* `subnet_id` - (Optional) The VPC Subnet ID to launch in.
@ -47,7 +47,7 @@ The following arguments are supported:
* `iam_instance_profile` - (Optional) The IAM Instance Profile to
launch the instance with.
* `tags` - (Optional) A mapping of tags to assign to the resource.
* `block_device` - (Optional) A list of block devices to add. Their keys are documented below.
* `block_device` - (Optional) An array of block devices to add. Their keys are documented below.
Each `block_device` supports the following:

View File

@ -30,7 +30,7 @@ The following arguments are supported:
* `iam_instance_profile` - (Optional) The IAM instance profile to associate
with launched instances.
* `key_name` - (Optional) The key name that should be used for the instance.
* `security_groups` - (Optional) A list of associated security group IDS.
* `security_groups` - (Optional) An array of associated security group IDS.
* `user_data` - (Optional) The user data to provide when launching the instance.
## Attributes Reference

View File

@ -30,7 +30,7 @@ The following arguments are supported:
* `name` - (Required) The name of the record.
* `type` - (Required) The record type.
* `ttl` - (Required) The TTL of the record.
* `records` - (Required) A string list of records.
* `records` - (Required) A string array of records.
## Attributes Reference

View File

@ -31,7 +31,7 @@ resource "aws_route_table" "r" {
The following arguments are supported:
* `vpc_id` - (Required) The ID of the routing table.
* `route` - (Optional) A list of route objects. Their keys are documented below.
* `route` - (Optional) An array of route objects. Their keys are documented below.
* `tags` - (Optional) A mapping of tags to assign to the resource.
Each route supports the following:

View File

@ -61,10 +61,10 @@ The following arguments are supported:
The `ingress` block supports:
* `cidr_blocks` - (Optional) List of CIDR blocks. Cannot be used with `security_groups`.
* `cidr_blocks` - (Optional) Array of CIDR blocks. Cannot be used with `security_groups`.
* `from_port` - (Required) The start port.
* `protocol` - (Required) The protocol.
* `security_groups` - (Optional) List of security group IDs. Cannot be used with `cidr_blocks`.
* `security_groups` - (Optional) Array of security group IDs. Cannot be used with `cidr_blocks`.
* `self` - (Optional) If true, the security group itself will be added as
a source to this ingress rule.
* `to_port` - (Required) The end range port.

View File

@ -47,7 +47,7 @@ The `rule` block supports:
* `icmp_code` - (Optional) The ICMP code to allow. This can only be specified if
the protocol is ICMP.
* `ports` - (Optional) List of ports and/or port ranges to allow. This can only
* `ports` - (Optional) Array of ports and/or port ranges to allow. This can only
be specified if the protocol is TCP or UDP.
## Attributes Reference

View File

@ -52,7 +52,7 @@ The `rule` block supports:
* `icmp_code` - (Optional) The ICMP code to allow. This can only be specified if
the protocol is ICMP.
* `ports` - (Optional) List of ports and/or port ranges to allow. This can only
* `ports` - (Optional) Array of ports and/or port ranges to allow. This can only
be specified if the protocol is TCP, UDP, ALL or a valid protocol number.
* `traffic_type` - (Optional) The traffic type for the rule. Valid options are:

View File

@ -35,7 +35,7 @@ The following arguments are supported:
* `backups` - (Optional) Boolean controlling if backups are made.
* `ipv6` - (Optional) Boolean controlling if IPv6 is enabled.
* `private_networking` - (Optional) Boolean controlling if private networks are enabled.
* `ssh_keys` - (Optional) A list of SSH IDs or fingerprints to enable in
* `ssh_keys` - (Optional) An array of SSH IDs or fingerprints to enable in
the format `[12345, 123456]`. To retrieve this info, use a tool such
as `curl` with the [DigitalOcean API](https://developers.digitalocean.com/#keys),
to retrieve them.

View File

@ -42,18 +42,18 @@ The following arguments are supported:
* `allow` - (Required) Can be specified multiple times for each allow
rule. Each allow block supports fields documented below.
* `source_ranges` - (Optional) A list of source CIDR ranges that this
* `source_ranges` - (Optional) An array of source CIDR ranges that this
firewall applies to.
* `source_tags` - (Optional) A list of source tags that this firewall applies to.
* `source_tags` - (Optional) An array of source tags that this firewall applies to.
* `target_tags` - (Optional) A list of target tags that this firewall applies to.
* `target_tags` - (Optional) An array of target tags that this firewall applies to.
The `allow` block supports:
* `protocol` - (Required) The name of the protocol to allow.
* `ports` - (Optional) List of ports and/or port ranges to allow. This can
* `ports` - (Optional) Array of ports and/or port ranges to allow. This can
only be specified if the protocol is TCP or UDP.
## Attributes Reference

View File

@ -90,7 +90,7 @@ The `network` block supports:
The `service_account` block supports:
* `scopes` - (Required) A list of service scopes. Both OAuth2 URLs and gcloud
* `scopes` - (Required) An array of service scopes. Both OAuth2 URLs and gcloud
short names are supported.
## Attributes Reference

View File

@ -37,7 +37,7 @@ The following arguments are supported:
The config variables in this map are not the final set of configuration
variables, but rather variables you want present. That is, other
configuration variables set externally won't be removed by Terraform
if they aren't present in this list.
if they aren't present in this array.
* `organization` - (Optional) A block that can be specified once to define
organization settings for this app. The fields for this block are
documented below.

View File

@ -34,14 +34,14 @@ resource "aws_instance" "web" {
The following arguments are supported:
* `inline` - This is a list of command strings. They are executed in the order
* `inline` - This is an array of command strings. They are executed in the order
they are provided. This cannot be provided with `script` or `scripts`.
* `script` - This is a path (relative or absolute) to a local script that will
be copied to the remote resource and then executed. This cannot be provided
with `inline` or `scripts`.
* `scripts` - This is a list of paths (relative or absolute) to local scripts
* `scripts` - This is an array of paths (relative or absolute) to local scripts
that will be copied to the remote resource and then executed. They are executed
in the order they are provided. This cannot be provided with `inline` or `script`.

View File

@ -13,7 +13,7 @@ description: |-
The count parameter on resources can simplify configurations
and let you scale resources by simply incrementing a number.
Additionally, variables can be used to expand a list of resources
Additionally, variables can be used to expand an array of resources
for use elsewhere.
As with all examples, just copy and paste the example and run