Merge branch 'terraform' into hmrc
This commit is contained in:
commit
815ff7ac63
|
@ -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]
|
||||
|
||||
|
|
6
Makefile
6
Makefile
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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}"]
|
||||
}
|
||||
`
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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/"
|
||||
}
|
||||
`
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue