Merge branch 'terraform' into hmrc

This commit is contained in:
Brett Mack 2015-11-18 17:56:28 +00:00
commit 815ff7ac63
14 changed files with 119 additions and 74 deletions

View File

@ -36,6 +36,7 @@ IMPROVEMENTS:
* provider/aws: Add a computed ARN for S3 Buckets [GH-3685]
* provider/aws: Add S3 support for Lambda Function resource [GH-3794]
* provider/aws: Add `name_prefix` option to launch configurations [GH-3802]
* provider/aws: add support for group name and path changes with IAM group update function [GH-3237]
* provider/aws: Provide `source_security_group_id` for ELBs inside a VPC [GH-3780]
* provider/aws: Add snapshot window and retention limits for ElastiCache (Redis) [GH-3707]
* provider/aws: Add username updates for `aws_iam_user` [GH-3227]
@ -55,6 +56,7 @@ IMPROVEMENTS:
* provider/vsphere: Do not add network interfaces by default [GH-3652]
* provider/openstack: Configure Fixed IPs through ports [GH-3772]
* provider/openstack: Specify a port ID on a Router Interface [GH-3903]
* provider/openstack: Made LBaaS Virtual IP computed [GH-3927]
BUG FIXES:
@ -70,6 +72,7 @@ BUG FIXES:
* provider/aws: ignore association not exist on route table destroy [GH-3615]
* provider/aws: Fix policy encoding issue with SNS Topics [GH-3700]
* provider/aws: Correctly export ARN in `aws_iam_saml_provider` [GH-3827]
* provider/aws: Fix crash in Route53 Record if Zone not found [GH-3945]
* provider/aws: Tolerate ElastiCache clusters being deleted outside Terraform [GH-3767]
* provider/aws: Downcase Route 53 record names in statefile to match API output [GH-3574]
* provider/aws: Fix issue that could occur if no ECS Cluster was found for a give name [GH-3829]
@ -79,6 +82,7 @@ BUG FIXES:
* provider/aws: Expand ~ to homedir in `aws_s3_bucket_object.source` [GH-3910]
* provider/aws: Fix issue with updating the `aws_ecs_task_definition` where `aws_ecs_service` didn't wait for a new computed ARN [GH-3924]
* provider/aws: Prevent crashing when deleting `aws_ecs_service` that is already gone [GH-3914]
* provider/aws: Allow spaces in `aws_db_subnet_group.name` (undocumented in the API) [GH-3955]
* provider/azure: various bugfixes [GH-3695]
* provider/digitalocean: fix issue preventing SSH fingerprints from working [GH-3633]
* provider/digitalocean: Fixing the DigitalOcean Droplet 404 potential on refresh of state [GH-3768]
@ -91,6 +95,7 @@ BUG FIXES:
* provider/openstack: Better handling of network resource state changes [GH-3712]
* provider/openstack: Fix crashing when no security group is specified [GH-3801]
* provider/packet: Fix issue that could cause errors when provisioning many devices at once [GH-3847]
* provider/packet: Fix connection information for devices, allowing provisioners to run [GH-3948]
* provider/openstack: Fix issue preventing security group rules from being removed [GH-3796]
* provider/template: template_file: source contents instead of path [GH-3909]

View File

@ -15,6 +15,12 @@ dev: generate
quickdev: generate
@TF_QUICKDEV=1 TF_DEV=1 sh -c "'$(CURDIR)/scripts/build.sh'"
# Shorthand for quickly building the core of Terraform. Note that some
# changes will require a rebuild of everything, in which case the dev
# target should be used.
core-dev: generate
go install github.com/hashicorp/terraform
# Shorthand for building and installing just one plugin for local testing.
# Run as (for example): make plugin-dev PLUGIN=provider-aws
plugin-dev: generate

View File

@ -29,9 +29,9 @@ func resourceAwsDbSubnetGroup() *schema.Resource {
Required: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[.0-9A-Za-z-_]+$`).MatchString(value) {
if !regexp.MustCompile(`^[ .0-9A-Za-z-_]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"only alphanumeric characters, hyphens, underscores, and periods allowed in %q", k))
"only alphanumeric characters, hyphens, underscores, periods, and spaces allowed in %q", k))
}
if len(value) > 255 {
errors = append(errors, fmt.Errorf(

View File

@ -51,12 +51,14 @@ func TestAccAWSDBSubnetGroup_withUndocumentedCharacters(t *testing.T) {
CheckDestroy: testAccCheckDBSubnetGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccDBSubnetGroupConfig_withUnderscoresAndPeriods,
Config: testAccDBSubnetGroupConfig_withUnderscoresAndPeriodsAndSpaces,
Check: resource.ComposeTestCheckFunc(
testAccCheckDBSubnetGroupExists(
"aws_db_subnet_group.underscores", &v),
testAccCheckDBSubnetGroupExists(
"aws_db_subnet_group.periods", &v),
testAccCheckDBSubnetGroupExists(
"aws_db_subnet_group.spaces", &v),
testCheck,
),
},
@ -156,7 +158,7 @@ resource "aws_db_subnet_group" "foo" {
}
`
const testAccDBSubnetGroupConfig_withUnderscoresAndPeriods = `
const testAccDBSubnetGroupConfig_withUnderscoresAndPeriodsAndSpaces = `
resource "aws_vpc" "main" {
cidr_block = "192.168.0.0/16"
}
@ -184,4 +186,10 @@ resource "aws_db_subnet_group" "periods" {
description = "Our main group of subnets"
subnet_ids = ["${aws_subnet.frontend.id}", "${aws_subnet.backend.id}"]
}
resource "aws_db_subnet_group" "spaces" {
name = "with spaces"
description = "Our main group of subnets"
subnet_ids = ["${aws_subnet.frontend.id}", "${aws_subnet.backend.id}"]
}
`

View File

@ -14,8 +14,7 @@ func resourceAwsIamGroup() *schema.Resource {
return &schema.Resource{
Create: resourceAwsIamGroupCreate,
Read: resourceAwsIamGroupRead,
// TODO
//Update: resourceAwsIamGroupUpdate,
Update: resourceAwsIamGroupUpdate,
Delete: resourceAwsIamGroupDelete,
Schema: map[string]*schema.Schema{
@ -30,13 +29,11 @@ func resourceAwsIamGroup() *schema.Resource {
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"path": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Default: "/",
ForceNew: true,
},
},
}
@ -45,9 +42,10 @@ func resourceAwsIamGroup() *schema.Resource {
func resourceAwsIamGroupCreate(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
name := d.Get("name").(string)
path := d.Get("path").(string)
request := &iam.CreateGroupInput{
Path: aws.String(d.Get("path").(string)),
Path: aws.String(path),
GroupName: aws.String(name),
}
@ -60,9 +58,10 @@ func resourceAwsIamGroupCreate(d *schema.ResourceData, meta interface{}) error {
func resourceAwsIamGroupRead(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
name := d.Get("name").(string)
request := &iam.GetGroupInput{
GroupName: aws.String(d.Id()),
GroupName: aws.String(name),
}
getResp, err := iamconn.GetGroup(request)
@ -93,6 +92,26 @@ func resourceAwsIamGroupReadResult(d *schema.ResourceData, group *iam.Group) err
return nil
}
func resourceAwsIamGroupUpdate(d *schema.ResourceData, meta interface{}) error {
if d.HasChange("name") || d.HasChange("path") {
iamconn := meta.(*AWSClient).iamconn
on, nn := d.GetChange("name")
_, np := d.GetChange("path")
request := &iam.UpdateGroupInput{
GroupName: aws.String(on.(string)),
NewGroupName: aws.String(nn.(string)),
NewPath: aws.String(np.(string)),
}
_, err := iamconn.UpdateGroup(request)
if err != nil {
return fmt.Errorf("Error updating IAM Group %s: %s", d.Id(), err)
}
return resourceAwsIamGroupRead(d, meta)
}
return nil
}
func resourceAwsIamGroupDelete(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn

View File

@ -23,7 +23,14 @@ func TestAccAWSIAMGroup_basic(t *testing.T) {
Config: testAccAWSGroupConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSGroupExists("aws_iam_group.group", &conf),
testAccCheckAWSGroupAttributes(&conf),
testAccCheckAWSGroupAttributes(&conf, "test-group", "/"),
),
},
resource.TestStep{
Config: testAccAWSGroupConfig2,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSGroupExists("aws_iam_group.group", &conf),
testAccCheckAWSGroupAttributes(&conf, "test-group2", "/funnypath/"),
),
},
},
@ -85,14 +92,14 @@ func testAccCheckAWSGroupExists(n string, res *iam.GetGroupOutput) resource.Test
}
}
func testAccCheckAWSGroupAttributes(group *iam.GetGroupOutput) resource.TestCheckFunc {
func testAccCheckAWSGroupAttributes(group *iam.GetGroupOutput, name string, path string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if *group.Group.GroupName != "test-group" {
return fmt.Errorf("Bad name: %s", *group.Group.GroupName)
if *group.Group.GroupName != name {
return fmt.Errorf("Bad name: %s when %s was expected", *group.Group.GroupName, name)
}
if *group.Group.Path != "/" {
return fmt.Errorf("Bad path: %s", *group.Group.Path)
if *group.Group.Path != path {
return fmt.Errorf("Bad path: %s when %s was expected", *group.Group.Path, path)
}
return nil
@ -105,3 +112,9 @@ resource "aws_iam_group" "group" {
path = "/"
}
`
const testAccAWSGroupConfig2 = `
resource "aws_iam_group" "group" {
name = "test-group2"
path = "/funnypath/"
}
`

View File

@ -49,6 +49,13 @@ func resourceAwsRoute53Record() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
value := v.(string)
if value == "" {
es = append(es, fmt.Errorf("Cannot have empty zone_id"))
}
return
},
},
"ttl": &schema.Schema{
@ -136,6 +143,9 @@ func resourceAwsRoute53RecordCreate(d *schema.ResourceData, meta interface{}) er
if err != nil {
return err
}
if zoneRecord.HostedZone == nil {
return fmt.Errorf("[WARN] No Route53 Zone found for id (%s)", zone)
}
// Get the record
rec, err := resourceAwsRoute53RecordBuildSet(d, *zoneRecord.HostedZone.Name)

View File

@ -3,7 +3,6 @@ package openstack
import (
"fmt"
"log"
"strconv"
"github.com/hashicorp/terraform/helper/schema"
"github.com/rackspace/gophercloud"
@ -53,16 +52,19 @@ func resourceLBVipV1() *schema.Resource {
"tenant_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"address": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: false,
},
"persistence": &schema.Schema{
@ -73,6 +75,7 @@ func resourceLBVipV1() *schema.Resource {
"conn_limit": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
ForceNew: false,
},
"port_id": &schema.Schema{
@ -86,8 +89,9 @@ func resourceLBVipV1() *schema.Resource {
ForceNew: false,
},
"admin_state_up": &schema.Schema{
Type: schema.TypeString,
Type: schema.TypeBool,
Optional: true,
Computed: true,
ForceNew: false,
},
},
@ -114,14 +118,8 @@ func resourceLBVipV1Create(d *schema.ResourceData, meta interface{}) error {
ConnLimit: gophercloud.MaybeInt(d.Get("conn_limit").(int)),
}
asuRaw := d.Get("admin_state_up").(string)
if asuRaw != "" {
asu, err := strconv.ParseBool(asuRaw)
if err != nil {
return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'")
}
createOpts.AdminStateUp = &asu
}
asu := d.Get("admin_state_up").(bool)
createOpts.AdminStateUp = &asu
log.Printf("[DEBUG] Create Options: %#v", createOpts)
p, err := vips.Create(networkingClient, createOpts).Extract()
@ -160,40 +158,11 @@ func resourceLBVipV1Read(d *schema.ResourceData, meta interface{}) error {
d.Set("port", p.ProtocolPort)
d.Set("pool_id", p.PoolID)
d.Set("port_id", p.PortID)
if t, exists := d.GetOk("tenant_id"); exists && t != "" {
d.Set("tenant_id", p.TenantID)
} else {
d.Set("tenant_id", "")
}
if t, exists := d.GetOk("address"); exists && t != "" {
d.Set("address", p.Address)
} else {
d.Set("address", "")
}
if t, exists := d.GetOk("description"); exists && t != "" {
d.Set("description", p.Description)
} else {
d.Set("description", "")
}
if t, exists := d.GetOk("persistence"); exists && t != "" {
d.Set("persistence", p.Description)
}
if t, exists := d.GetOk("conn_limit"); exists && t != "" {
d.Set("conn_limit", p.ConnLimit)
} else {
d.Set("conn_limit", "")
}
if t, exists := d.GetOk("admin_state_up"); exists && t != "" {
d.Set("admin_state_up", strconv.FormatBool(p.AdminStateUp))
} else {
d.Set("admin_state_up", "")
}
d.Set("tenant_id", p.TenantID)
d.Set("address", p.Address)
d.Set("description", p.Description)
d.Set("conn_limit", p.ConnLimit)
d.Set("admin_state_up", p.AdminStateUp)
return nil
}
@ -255,14 +224,8 @@ func resourceLBVipV1Update(d *schema.ResourceData, meta interface{}) error {
}
}
if d.HasChange("admin_state_up") {
asuRaw := d.Get("admin_state_up").(string)
if asuRaw != "" {
asu, err := strconv.ParseBool(asuRaw)
if err != nil {
return fmt.Errorf("admin_state_up, if provided, must be either 'true' or 'false'")
}
updateOpts.AdminStateUp = &asu
}
asu := d.Get("admin_state_up").(bool)
updateOpts.AdminStateUp = &asu
}
log.Printf("[DEBUG] Updating OpenStack LB VIP %s with options: %+v", d.Id(), updateOpts)

View File

@ -116,6 +116,9 @@ var testAccLBV1VIP_basic = fmt.Sprintf(`
protocol = "HTTP"
port = 80
pool_id = "${openstack_lb_pool_v1.pool_1.id}"
persistence {
type = "SOURCE_IP"
}
}`,
OS_REGION_NAME, OS_REGION_NAME, OS_REGION_NAME)
@ -148,5 +151,8 @@ var testAccLBV1VIP_update = fmt.Sprintf(`
protocol = "HTTP"
port = 80
pool_id = "${openstack_lb_pool_v1.pool_1.id}"
persistence {
type = "SOURCE_IP"
}
}`,
OS_REGION_NAME, OS_REGION_NAME, OS_REGION_NAME)

View File

@ -184,7 +184,7 @@ func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
d.Set("billing_cycle", device.BillingCycle)
d.Set("locked", device.Locked)
d.Set("created", device.Created)
d.Set("udpated", device.Updated)
d.Set("updated", device.Updated)
tags := make([]string, 0)
for _, tag := range device.Tags {
@ -192,6 +192,8 @@ func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
}
d.Set("tags", tags)
provisionerAddress := ""
networks := make([]map[string]interface{}, 0, 1)
for _, ip := range device.Network {
network := make(map[string]interface{})
@ -201,9 +203,21 @@ func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
network["cidr"] = ip.Cidr
network["public"] = ip.Public
networks = append(networks, network)
if ip.Family == 4 && ip.Public == true {
provisionerAddress = ip.Address
}
}
d.Set("network", networks)
log.Printf("[DEBUG] Provisioner Address set to %v", provisionerAddress)
if provisionerAddress != "" {
d.SetConnInfo(map[string]string{
"type": "ssh",
"host": provisionerAddress,
})
}
return nil
}

View File

@ -19,7 +19,7 @@ resource "cloudstack_disk" "default" {
attach = "true"
disk_offering = "custom"
size = 50
virtual-machine = "server-1"
virtual_machine = "server-1"
zone = "zone-1"
}
```

View File

@ -14,7 +14,7 @@ Renders a template from a file.
```
resource "template_file" "init" {
template = "${file(${path.module}/init.tpl)}"
template = "${file("${path.module}/init.tpl")}"
vars {
consul_address = "${aws_instance.consul.private_ip}"

View File

@ -17,7 +17,8 @@ The provider needs to be configured with the proper credentials before it can be
Use the navigation to the left to read about the available resources.
~> **NOTE:** The VMware vSphere Provider currently represents _initial support_
and therefore may undergo significant changes as the community improves it.
and therefore may undergo significant changes as the community improves it. This
provider at this time only supports IPv4 addresses on virtual machines.
## Example Usage
@ -72,7 +73,7 @@ In addition, the following environment variables are used in tests, and must be
* VSPHERE\_TEMPLATE
The following environment variables depend on your vSphere environment:
* VSPHERE\_DATACENTER
* VSPHERE\_CLUSTER
* VSPHERE\_RESOURCE\_POOL

View File

@ -55,7 +55,7 @@ The following arguments are supported:
Network interfaces support the following attributes:
* `label` - (Required) Label to assign to this network interface
* `ip_address` - (Optional) Static IP to assign to this network interface. Interface will use DHCP if this is left blank.
* `ip_address` - (Optional) Static IP to assign to this network interface. Interface will use DHCP if this is left blank. Currently only IPv4 IP addresses are supported.
* `subnet_mask` - (Optional) Subnet mask to use when statically assigning an IP.
<a id="disks"></a>