From 804d714ff644cdcd8fd4a42ebf4831aa94826d4d Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Sat, 24 Sep 2016 12:22:07 -0700 Subject: [PATCH 01/16] Restore tls_cert_request to being a managed resource In c244e5a6 this resource was converted to a data source, but that was a mistake since data sources are expected to produce stable results on each run, and yet certificate requests contain a random nonce as part of the signature. Additionally, using the data source as a managed resource through the provided compatibility shim was not actually working, since "Read" was trying to parse the private key out of a SHA1 hash of the key, which is what we place in state due to the StateFunc on that attribute. By restoring this we restore Terraform's ability to produce all of the parts of a basic PKI/CA, which is useful for creating dev environments and bootstrapping PKI for production environments. --- builtin/providers/tls/provider.go | 9 +------- ...rt_request.go => resource_cert_request.go} | 22 ++++++++++++++++--- ..._test.go => resource_cert_request_test.go} | 6 ++--- .../tls/{d => r}/cert_request.html.md | 12 +++++++++- website/source/layouts/tls.erb | 12 +++------- 5 files changed, 37 insertions(+), 24 deletions(-) rename builtin/providers/tls/{data_source_cert_request.go => resource_cert_request.go} (86%) rename builtin/providers/tls/{data_source_cert_request_test.go => resource_cert_request_test.go} (96%) rename website/source/docs/providers/tls/{d => r}/cert_request.html.md (76%) diff --git a/builtin/providers/tls/provider.go b/builtin/providers/tls/provider.go index 6f3363a95..e6c1d6198 100644 --- a/builtin/providers/tls/provider.go +++ b/builtin/providers/tls/provider.go @@ -12,18 +12,11 @@ import ( func Provider() terraform.ResourceProvider { return &schema.Provider{ - DataSourcesMap: map[string]*schema.Resource{ - "tls_cert_request": dataSourceCertRequest(), - }, ResourcesMap: map[string]*schema.Resource{ "tls_private_key": resourcePrivateKey(), "tls_locally_signed_cert": resourceLocallySignedCert(), "tls_self_signed_cert": resourceSelfSignedCert(), - - "tls_cert_request": schema.DataSourceResourceShim( - "tls_cert_request", - dataSourceCertRequest(), - ), + "tls_cert_request": resourceCertRequest(), }, } } diff --git a/builtin/providers/tls/data_source_cert_request.go b/builtin/providers/tls/resource_cert_request.go similarity index 86% rename from builtin/providers/tls/data_source_cert_request.go rename to builtin/providers/tls/resource_cert_request.go index 19bcd3129..267f0db39 100644 --- a/builtin/providers/tls/data_source_cert_request.go +++ b/builtin/providers/tls/resource_cert_request.go @@ -12,9 +12,11 @@ import ( const pemCertReqType = "CERTIFICATE REQUEST" -func dataSourceCertRequest() *schema.Resource { +func resourceCertRequest() *schema.Resource { return &schema.Resource{ - Read: ReadCertRequest, + Create: CreateCertRequest, + Delete: DeleteCertRequest, + Read: ReadCertRequest, Schema: map[string]*schema.Schema{ @@ -22,6 +24,7 @@ func dataSourceCertRequest() *schema.Resource { Type: schema.TypeList, Optional: true, Description: "List of DNS names to use as subjects of the certificate", + ForceNew: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -31,6 +34,7 @@ func dataSourceCertRequest() *schema.Resource { Type: schema.TypeList, Optional: true, Description: "List of IP addresses to use as subjects of the certificate", + ForceNew: true, Elem: &schema.Schema{ Type: schema.TypeString, }, @@ -40,12 +44,14 @@ func dataSourceCertRequest() *schema.Resource { Type: schema.TypeString, Required: true, Description: "Name of the algorithm to use to generate the certificate's private key", + ForceNew: true, }, "private_key_pem": &schema.Schema{ Type: schema.TypeString, Required: true, Description: "PEM-encoded private key that the certificate will belong to", + ForceNew: true, StateFunc: func(v interface{}) string { return hashForState(v.(string)) }, @@ -55,6 +61,7 @@ func dataSourceCertRequest() *schema.Resource { Type: schema.TypeList, Required: true, Elem: nameSchema, + ForceNew: true, }, "cert_request_pem": &schema.Schema{ @@ -65,7 +72,7 @@ func dataSourceCertRequest() *schema.Resource { } } -func ReadCertRequest(d *schema.ResourceData, meta interface{}) error { +func CreateCertRequest(d *schema.ResourceData, meta interface{}) error { key, err := parsePrivateKey(d, "private_key_pem", "key_algorithm") if err != nil { return err @@ -109,3 +116,12 @@ func ReadCertRequest(d *schema.ResourceData, meta interface{}) error { return nil } + +func DeleteCertRequest(d *schema.ResourceData, meta interface{}) error { + d.SetId("") + return nil +} + +func ReadCertRequest(d *schema.ResourceData, meta interface{}) error { + return nil +} diff --git a/builtin/providers/tls/data_source_cert_request_test.go b/builtin/providers/tls/resource_cert_request_test.go similarity index 96% rename from builtin/providers/tls/data_source_cert_request_test.go rename to builtin/providers/tls/resource_cert_request_test.go index 16cd29264..c31b8d6a1 100644 --- a/builtin/providers/tls/data_source_cert_request_test.go +++ b/builtin/providers/tls/resource_cert_request_test.go @@ -12,12 +12,12 @@ import ( ) func TestCertRequest(t *testing.T) { - r.UnitTest(t, r.TestCase{ + r.Test(t, r.TestCase{ Providers: testProviders, Steps: []r.TestStep{ r.TestStep{ Config: fmt.Sprintf(` - data "tls_cert_request" "test" { + resource "tls_cert_request" "test" { subject { common_name = "example.com" organization = "Example, Inc" @@ -46,7 +46,7 @@ func TestCertRequest(t *testing.T) { EOT } output "key_pem" { - value = "${data.tls_cert_request.test.cert_request_pem}" + value = "${tls_cert_request.test.cert_request_pem}" } `, testPrivateKey), Check: func(s *terraform.State) error { diff --git a/website/source/docs/providers/tls/d/cert_request.html.md b/website/source/docs/providers/tls/r/cert_request.html.md similarity index 76% rename from website/source/docs/providers/tls/d/cert_request.html.md rename to website/source/docs/providers/tls/r/cert_request.html.md index c61308f12..8869aeac6 100644 --- a/website/source/docs/providers/tls/d/cert_request.html.md +++ b/website/source/docs/providers/tls/r/cert_request.html.md @@ -13,11 +13,21 @@ typical format used to request a certificate from a certificate authority. This resource is intended to be used in conjunction with a Terraform provider for a particular certificate authority in order to provision a new certificate. +This is a *logical resource*, so it contributes only to the current Terraform +state and does not create any external managed resources. + +~> **Compatibility Note** From Terraform 0.7.0 to 0.7.4 this resource was +converted to a data source, and the resource form of it was deprecated. This +turned out to be a design error since a cert request includes a random number +in the form of the signature nonce, and so the data source form of this +resource caused non-convergent configuration. The data source form is no longer +supported as of Terraform 0.7.5 and any users should return to using the +resource form. ## Example Usage ``` -data "tls_cert_request" "example" { +resource "tls_cert_request" "example" { key_algorithm = "ECDSA" private_key_pem = "${file(\"private_key.pem\")}" diff --git a/website/source/layouts/tls.erb b/website/source/layouts/tls.erb index 2cc50eac0..97be3879c 100644 --- a/website/source/layouts/tls.erb +++ b/website/source/layouts/tls.erb @@ -10,15 +10,6 @@ TLS Provider - > - Data Sources - - - > Resources From 7337a346ecfa68615ad921e47c717c01705b11fe Mon Sep 17 00:00:00 2001 From: Clint Date: Thu, 29 Sep 2016 13:01:09 -0500 Subject: [PATCH 02/16] provider/aws: Fix issue with updating ELB subnets for subnets in the same AZ (#9131) * provider/aws: Regression test for #9120 * provider/aws: Fix issue with updating ELB subnets for subnets in the same AZ --- builtin/providers/aws/resource_aws_elb.go | 40 +++-- .../providers/aws/resource_aws_elb_test.go | 154 ++++++++++++++++++ 2 files changed, 181 insertions(+), 13 deletions(-) diff --git a/builtin/providers/aws/resource_aws_elb.go b/builtin/providers/aws/resource_aws_elb.go index 84323a698..6f2fb610c 100644 --- a/builtin/providers/aws/resource_aws_elb.go +++ b/builtin/providers/aws/resource_aws_elb.go @@ -695,19 +695,6 @@ func resourceAwsElbUpdate(d *schema.ResourceData, meta interface{}) error { removed := expandStringList(os.Difference(ns).List()) added := expandStringList(ns.Difference(os).List()) - if len(added) > 0 { - attachOpts := &elb.AttachLoadBalancerToSubnetsInput{ - LoadBalancerName: aws.String(d.Id()), - Subnets: added, - } - - log.Printf("[DEBUG] ELB attach subnets opts: %s", attachOpts) - _, err := elbconn.AttachLoadBalancerToSubnets(attachOpts) - if err != nil { - return fmt.Errorf("Failure adding ELB subnets: %s", err) - } - } - if len(removed) > 0 { detachOpts := &elb.DetachLoadBalancerFromSubnetsInput{ LoadBalancerName: aws.String(d.Id()), @@ -721,6 +708,33 @@ func resourceAwsElbUpdate(d *schema.ResourceData, meta interface{}) error { } } + if len(added) > 0 { + attachOpts := &elb.AttachLoadBalancerToSubnetsInput{ + LoadBalancerName: aws.String(d.Id()), + Subnets: added, + } + + log.Printf("[DEBUG] ELB attach subnets opts: %s", attachOpts) + err := resource.Retry(1*time.Minute, func() *resource.RetryError { + _, err := elbconn.AttachLoadBalancerToSubnets(attachOpts) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok { + // eventually consistent issue with removing a subnet in AZ1 and + // immediately adding a new one in the same AZ + if awsErr.Code() == "InvalidConfigurationRequest" && strings.Contains(awsErr.Message(), "cannot be attached to multiple subnets in the same AZ") { + log.Printf("[DEBUG] retrying az association") + return resource.RetryableError(awsErr) + } + } + return resource.NonRetryableError(err) + } + return nil + }) + if err != nil { + return fmt.Errorf("Failure adding ELB subnets: %s", err) + } + } + d.SetPartial("subnets") } diff --git a/builtin/providers/aws/resource_aws_elb_test.go b/builtin/providers/aws/resource_aws_elb_test.go index 6a676fd4d..0115705fd 100644 --- a/builtin/providers/aws/resource_aws_elb_test.go +++ b/builtin/providers/aws/resource_aws_elb_test.go @@ -248,6 +248,36 @@ func TestAccAWSELB_iam_server_cert(t *testing.T) { }) } +func TestAccAWSELB_swap_subnets(t *testing.T) { + var conf elb.LoadBalancerDescription + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_elb.ourapp", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSELBDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSELBConfig_subnets, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSELBExists("aws_elb.ourapp", &conf), + resource.TestCheckResourceAttr( + "aws_elb.ourapp", "subnets.#", "2"), + ), + }, + + resource.TestStep{ + Config: testAccAWSELBConfig_subnet_swap, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSELBExists("aws_elb.ourapp", &conf), + resource.TestCheckResourceAttr( + "aws_elb.ourapp", "subnets.#", "2"), + ), + }, + }, + }) +} + func testAccLoadTags(conf *elb.LoadBalancerDescription, td *elb.TagDescription) resource.TestCheckFunc { return func(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).elbconn @@ -1329,3 +1359,127 @@ resource "aws_elb" "bar" { } `, certName) } + +const testAccAWSELBConfig_subnets = ` +provider "aws" { + region = "us-west-2" +} + +resource "aws_vpc" "azelb" { + cidr_block = "10.1.0.0/16" + enable_dns_hostnames = true + + tags { + Name = "subnet-vpc" + } +} + +resource "aws_subnet" "public_a_one" { + vpc_id = "${aws_vpc.azelb.id}" + + cidr_block = "10.1.1.0/24" + availability_zone = "us-west-2a" +} + +resource "aws_subnet" "public_b_one" { + vpc_id = "${aws_vpc.azelb.id}" + + cidr_block = "10.1.7.0/24" + availability_zone = "us-west-2b" +} + +resource "aws_subnet" "public_a_two" { + vpc_id = "${aws_vpc.azelb.id}" + + cidr_block = "10.1.2.0/24" + availability_zone = "us-west-2a" +} + +resource "aws_elb" "ourapp" { + name = "terraform-asg-deployment-example" + + subnets = [ + "${aws_subnet.public_a_one.id}", + "${aws_subnet.public_b_one.id}", + ] + + listener { + instance_port = 80 + instance_protocol = "http" + lb_port = 80 + lb_protocol = "http" + } + + depends_on = ["aws_internet_gateway.gw"] +} + +resource "aws_internet_gateway" "gw" { + vpc_id = "${aws_vpc.azelb.id}" + + tags { + Name = "main" + } +} +` + +const testAccAWSELBConfig_subnet_swap = ` +provider "aws" { + region = "us-west-2" +} + +resource "aws_vpc" "azelb" { + cidr_block = "10.1.0.0/16" + enable_dns_hostnames = true + + tags { + Name = "subnet-vpc" + } +} + +resource "aws_subnet" "public_a_one" { + vpc_id = "${aws_vpc.azelb.id}" + + cidr_block = "10.1.1.0/24" + availability_zone = "us-west-2a" +} + +resource "aws_subnet" "public_b_one" { + vpc_id = "${aws_vpc.azelb.id}" + + cidr_block = "10.1.7.0/24" + availability_zone = "us-west-2b" +} + +resource "aws_subnet" "public_a_two" { + vpc_id = "${aws_vpc.azelb.id}" + + cidr_block = "10.1.2.0/24" + availability_zone = "us-west-2a" +} + +resource "aws_elb" "ourapp" { + name = "terraform-asg-deployment-example" + + subnets = [ + "${aws_subnet.public_a_two.id}", + "${aws_subnet.public_b_one.id}", + ] + + listener { + instance_port = 80 + instance_protocol = "http" + lb_port = 80 + lb_protocol = "http" + } + + depends_on = ["aws_internet_gateway.gw"] +} + +resource "aws_internet_gateway" "gw" { + vpc_id = "${aws_vpc.azelb.id}" + + tags { + Name = "main" + } +} +` From 654686496ceeca9ede0767613bd306b0cd005f6b Mon Sep 17 00:00:00 2001 From: Clint Date: Thu, 29 Sep 2016 13:02:37 -0500 Subject: [PATCH 03/16] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75cc6e686..1ef29c189 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ BUG FIXES: * provider/aws: aws_db_option_group flattenOptions failing due to missing values [GH-9052] * provider/aws: Add retry logic to the aws_ecr_repository delete func [GH-9050] * provider/aws: Modifying the parameter_group_name of aws_elasticache_replication_group caused a panic [GH-9101] + * provider/aws: Fix issue with updating ELB subnets for subnets in the same AZ [GH-9131] * provider/librato: Mandatory name and conditions attributes weren't being sent on Update unless changed [GH-8984] From f6ce1ff5a5859f746b5c7d2c72e62d39c00facd3 Mon Sep 17 00:00:00 2001 From: Alex Meng Date: Thu, 29 Sep 2016 14:40:57 -0600 Subject: [PATCH 04/16] Docs: Example import for cloudfront_distribution --- .../aws/r/cloudfront_distribution.html.markdown | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/website/source/docs/providers/aws/r/cloudfront_distribution.html.markdown b/website/source/docs/providers/aws/r/cloudfront_distribution.html.markdown index dbbf35d2f..016d268e5 100644 --- a/website/source/docs/providers/aws/r/cloudfront_distribution.html.markdown +++ b/website/source/docs/providers/aws/r/cloudfront_distribution.html.markdown @@ -369,3 +369,12 @@ The following attributes are exported: [5]: /docs/providers/aws/r/cloudfront_origin_access_identity.html [6]: https://aws.amazon.com/certificate-manager/ [7]: http://docs.aws.amazon.com/Route53/latest/APIReference/CreateAliasRRSAPI.html + + +## Import + +Cloudfront Distributions can be imported using the `id`, e.g. + +``` +$ terraform import aws_cloudfront_distribution.distribution E74FTE3EXAMPLE +``` From 489d5bd513d1d2b13d5ca324b93993f3598a30c6 Mon Sep 17 00:00:00 2001 From: James Nugent Date: Thu, 29 Sep 2016 17:02:32 -0500 Subject: [PATCH 05/16] deps: Update github.com/jen20/awspolicyequivalence This fixes a bug in the upstream library where different casing of `effect` was not treated as equivalent. --- .../awspolicyequivalence/aws_policy_equivalence.go | 13 ++++++------- vendor/vendor.json | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/vendor/github.com/jen20/awspolicyequivalence/aws_policy_equivalence.go b/vendor/github.com/jen20/awspolicyequivalence/aws_policy_equivalence.go index 8c2a66c48..9aef4ca81 100644 --- a/vendor/github.com/jen20/awspolicyequivalence/aws_policy_equivalence.go +++ b/vendor/github.com/jen20/awspolicyequivalence/aws_policy_equivalence.go @@ -1,8 +1,9 @@ package awspolicy import ( - "reflect" "encoding/json" + "reflect" + "strings" "github.com/hashicorp/errwrap" ) @@ -104,7 +105,7 @@ func (statement *awsPolicyStatement) equals(other *awsPolicyStatement) bool { return false } - if statement.Effect != other.Effect { + if strings.ToLower(statement.Effect) != strings.ToLower(other.Effect) { return false } @@ -164,7 +165,7 @@ func mapPrincipalsEqual(ours, theirs interface{}) bool { } theirPrincipalMap, ok := theirs.(map[string]interface{}) - if ! ok { + if !ok { return false } @@ -218,7 +219,6 @@ func stringPrincipalsEqual(ours, theirs interface{}) bool { return false } - type awsConditionsBlock map[string]map[string]interface{} func (conditions awsConditionsBlock) Equals(other awsConditionsBlock) bool { @@ -256,7 +256,7 @@ func (conditions awsConditionsBlock) Equals(other awsConditionsBlock) bool { for innerKey, oursInner := range ours { theirsInner, ok := theirs[innerKey] - if ! ok { + if !ok { return false } @@ -274,7 +274,7 @@ func (conditions awsConditionsBlock) Equals(other awsConditionsBlock) bool { for innerKey, theirsInner := range theirs { oursInner, ok := ours[innerKey] - if ! ok { + if !ok { return false } @@ -287,7 +287,6 @@ func (conditions awsConditionsBlock) Equals(other awsConditionsBlock) bool { return true } - type awsStringSet []string // newAWSStringSet constructs an awsStringSet from an interface{} - which diff --git a/vendor/vendor.json b/vendor/vendor.json index 3e9621e11..3adfb3bc6 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1291,10 +1291,10 @@ "revision": "f233a8bac88d1f2dc282a98186f5a3363b806181" }, { - "checksumSHA1": "cCSJGF1h+suYcgMq7wEm1carknw=", + "checksumSHA1": "zyyyjWKu9gGLFy00k8utV7pncvg=", "path": "github.com/jen20/awspolicyequivalence", - "revision": "6b9230008577fc3dcd10c104ce8fb16ed679bf66", - "revisionTime": "2016-09-01T18:24:20Z" + "revision": "ebe5485f2c1822e7bee8b5008e14d9481a14a3a3", + "revisionTime": "2016-09-29T21:48:42Z" }, { "checksumSHA1": "oPpOfZn11Ef6DWOoETxSW9Venzs=", From 1cbef59c8d911c51ea98e5113c2fa351b06d7f64 Mon Sep 17 00:00:00 2001 From: James Nugent Date: Thu, 29 Sep 2016 17:07:06 -0500 Subject: [PATCH 06/16] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ef29c189..daf5978d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ IMPROVEMENTS: BUG FIXES: * core: Fixed variables not being in scope for destroy -target on modules [GH-9021] * provider/aws: Remove support for `ah` and `esp` literals in Security Group Ingress/Egress rules; you must use the actual protocol number for protocols other than `tcp`, `udp`, `icmp`, or `all` [GH-8975] + * provider/aws: Do not report drift for effect values differing only by case in AWS policies [GH-9139] * provider/aws: VPC ID, Port, Protocol and Name change on aws_alb_target_group will ForceNew resource [GH-8989] * provider/aws: Wait for Spot Fleet to drain before removing from state [GH-8938] * provider/aws: Fix issue when importing `aws_eip` resources by IP address [GH-8970] From bd083f84f376adaec43206c453b948f96e325213 Mon Sep 17 00:00:00 2001 From: James Nugent Date: Fri, 30 Sep 2016 00:31:51 -0500 Subject: [PATCH 07/16] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index daf5978d2..b441a417f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## 0.7.5 (Unreleased) +BACKWARDS INCOMPATIBILITIES / NOTES: + * `tls_cert_request` is now a managed resource instead of a data source, restoring the pre-Terraform 0.7 behaviour [GH-9035] + FEATURES: * **New Provider:** `bitbucket` [GH-7405] * **New Resource:** `aws_api_gateway_client_certificate` [GH-8775] From 34764c52afe5cea7c066a67f5891073ec8bee613 Mon Sep 17 00:00:00 2001 From: dnABic Date: Fri, 30 Sep 2016 22:41:15 +0200 Subject: [PATCH 08/16] mostly typos in documens and aws autoscaling id instead of name --- website/source/docs/internals/debugging.html.md | 2 +- .../docs/providers/aws/r/autoscaling_group.html.markdown | 2 +- .../source/docs/providers/aws/r/efs_file_system.html.markdown | 2 +- .../docs/providers/aws/r/opsworks_permission.html.markdown | 4 ++-- website/source/docs/providers/logentries/r/log.html.markdown | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/website/source/docs/internals/debugging.html.md b/website/source/docs/internals/debugging.html.md index b19000b39..b5fe73b6b 100644 --- a/website/source/docs/internals/debugging.html.md +++ b/website/source/docs/internals/debugging.html.md @@ -27,7 +27,7 @@ to the developers via a GitHub Issue. As a user, you're not required to dig into this file. However, if you are interested in figuring out what might have gone wrong -before filing an issue, here are the the basic details of how to read a crash +before filing an issue, here are the basic details of how to read a crash log. The most interesting part of a crash log is the panic message itself and the diff --git a/website/source/docs/providers/aws/r/autoscaling_group.html.markdown b/website/source/docs/providers/aws/r/autoscaling_group.html.markdown index 4e7755cb6..34cca690b 100644 --- a/website/source/docs/providers/aws/r/autoscaling_group.html.markdown +++ b/website/source/docs/providers/aws/r/autoscaling_group.html.markdown @@ -103,7 +103,7 @@ Tags support the following: The following attributes are exported: -* `id` - The autoscaling group name. +* `id` - The autoscaling group id. * `arn` - The ARN for this AutoScaling Group * `availability_zones` - The availability zones of the autoscale group. * `min_size` - The minimum size of the autoscale group diff --git a/website/source/docs/providers/aws/r/efs_file_system.html.markdown b/website/source/docs/providers/aws/r/efs_file_system.html.markdown index c8f49289f..4a4785e01 100644 --- a/website/source/docs/providers/aws/r/efs_file_system.html.markdown +++ b/website/source/docs/providers/aws/r/efs_file_system.html.markdown @@ -29,7 +29,7 @@ be removed in future releases, please use `creation_token` instead. The following arguments are supported: * `creation_token` - (Optional) A unique name (a maximum of 64 characters are allowed) -used as reference when creating the the Elastic File System to ensure idempotent file +used as reference when creating the Elastic File System to ensure idempotent file system creation. By default generated by Terraform. See [Elastic File System] (http://docs.aws.amazon.com/efs/latest/ug/) user guide for more information. * `reference_name` - **DEPRECATED** (Optional) A reference name used when creating the diff --git a/website/source/docs/providers/aws/r/opsworks_permission.html.markdown b/website/source/docs/providers/aws/r/opsworks_permission.html.markdown index 6d7d93a09..d5dd063c2 100644 --- a/website/source/docs/providers/aws/r/opsworks_permission.html.markdown +++ b/website/source/docs/providers/aws/r/opsworks_permission.html.markdown @@ -26,8 +26,8 @@ resource "aws_opsworks_permission" "my_stack_permission" { The following arguments are supported: -* `allow_ssh` - (Optional) Whethe the user is allowed to use SSH to communicate with the instance -* `allow_sudo` - (Optional) Whethe the user is allowed to use sudo to elevate privileges +* `allow_ssh` - (Optional) Whether the user is allowed to use SSH to communicate with the instance +* `allow_sudo` - (Optional) Whether the user is allowed to use sudo to elevate privileges * `user_arn` - (Required) The user's IAM ARN to set permissions for * `level` - (Optional) The users permission level. Mus be one of `deny`, `show`, `deploy`, `manage`, `iam_only` * `stack_id` - (Required) The stack to set the permissions for diff --git a/website/source/docs/providers/logentries/r/log.html.markdown b/website/source/docs/providers/logentries/r/log.html.markdown index 5045965ef..eaeedd299 100644 --- a/website/source/docs/providers/logentries/r/log.html.markdown +++ b/website/source/docs/providers/logentries/r/log.html.markdown @@ -35,4 +35,4 @@ The following arguments are supported: The following attributes are exported: -* `token` - If the the log `source` is `token`, this value holds the generated log token that is used by logging clients. See the Logentries [token-based input documentation](https://logentries.com/doc/input-token/) for more information. +* `token` - If the log `source` is `token`, this value holds the generated log token that is used by logging clients. See the Logentries [token-based input documentation](https://logentries.com/doc/input-token/) for more information. From 6282c0fabff9ccedcced13452e76c8f740d0fc3b Mon Sep 17 00:00:00 2001 From: clint shryock Date: Thu, 22 Sep 2016 11:47:15 -0500 Subject: [PATCH 09/16] provider/aws: Regression test for NetAcl + ESP protocol --- .../aws/resource_aws_network_acl_test.go | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index 4c54c84de..7fcb6a5e9 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -228,7 +228,25 @@ func TestAccAWSNetworkAcl_Subnets(t *testing.T) { }, }, }) +} +func TestAccAWSNetworkAcl_espProtocol(t *testing.T) { + var networkAcl ec2.NetworkAcl + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_network_acl.testesp", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSNetworkAclDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSNetworkAclEsp, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSNetworkAclExists("aws_network_acl.testesp", &networkAcl), + ), + }, + }, + }) } func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { @@ -638,3 +656,26 @@ resource "aws_network_acl" "bar" { } } ` + +const testAccAWSNetworkAclEsp = ` +resource "aws_vpc" "testespvpc" { + cidr_block = "10.1.0.0/16" +} + +resource "aws_network_acl" "testesp" { + vpc_id = "${aws_vpc.testespvpc.id}" + + egress { + protocol = "esp" + rule_no = 5 + action = "allow" + cidr_block = "10.3.0.0/18" + from_port = 0 + to_port = 0 + } + + tags { + Name = "test_esp" + } +} +` From 2cc28f6137890105429bebdf98ef0853923bee77 Mon Sep 17 00:00:00 2001 From: clint shryock Date: Thu, 22 Sep 2016 11:48:31 -0500 Subject: [PATCH 10/16] revert netacl protocolIntegers change from 45da08c67f91274ea8b67af210b600497be50388 --- builtin/providers/aws/network_acl_entry.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builtin/providers/aws/network_acl_entry.go b/builtin/providers/aws/network_acl_entry.go index 84937af6a..cb718462c 100644 --- a/builtin/providers/aws/network_acl_entry.go +++ b/builtin/providers/aws/network_acl_entry.go @@ -82,6 +82,8 @@ func protocolIntegers() map[string]int { var protocolIntegers = make(map[string]int) protocolIntegers = map[string]int{ // defined at https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + "ah": 51, + "esp": 50, "udp": 17, "tcp": 6, "icmp": 1, From de3a7b5d204cb11d96b562f92e4f891a1f47bfd6 Mon Sep 17 00:00:00 2001 From: clint shryock Date: Thu, 22 Sep 2016 13:30:32 -0500 Subject: [PATCH 11/16] give security groups their own sgProtocolIntegers methodw --- builtin/providers/aws/network_acl_entry.go | 4 +-- .../aws/resource_aws_network_acl_test.go | 30 +++++++++---------- .../aws/resource_aws_security_group.go | 21 +++++++++++-- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/builtin/providers/aws/network_acl_entry.go b/builtin/providers/aws/network_acl_entry.go index cb718462c..5a09746d6 100644 --- a/builtin/providers/aws/network_acl_entry.go +++ b/builtin/providers/aws/network_acl_entry.go @@ -82,8 +82,8 @@ func protocolIntegers() map[string]int { var protocolIntegers = make(map[string]int) protocolIntegers = map[string]int{ // defined at https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml - "ah": 51, - "esp": 50, + "ah": 51, + "esp": 50, "udp": 17, "tcp": 6, "icmp": 1, diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index 7fcb6a5e9..c63f5c008 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -231,22 +231,22 @@ func TestAccAWSNetworkAcl_Subnets(t *testing.T) { } func TestAccAWSNetworkAcl_espProtocol(t *testing.T) { - var networkAcl ec2.NetworkAcl + var networkAcl ec2.NetworkAcl - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "aws_network_acl.testesp", - Providers: testAccProviders, - CheckDestroy: testAccCheckAWSNetworkAclDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccAWSNetworkAclEsp, - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSNetworkAclExists("aws_network_acl.testesp", &networkAcl), - ), - }, - }, - }) + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_network_acl.testesp", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSNetworkAclDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSNetworkAclEsp, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSNetworkAclExists("aws_network_acl.testesp", &networkAcl), + ), + }, + }, + }) } func testAccCheckAWSNetworkAclDestroy(s *terraform.State) error { diff --git a/builtin/providers/aws/resource_aws_security_group.go b/builtin/providers/aws/resource_aws_security_group.go index 15cfcb0e0..4c34fea96 100644 --- a/builtin/providers/aws/resource_aws_security_group.go +++ b/builtin/providers/aws/resource_aws_security_group.go @@ -955,7 +955,7 @@ func protocolForValue(v string) string { return "-1" } // if it's a name like tcp, return that - if _, ok := protocolIntegers()[protocol]; ok { + if _, ok := sgProtocolIntegers()[protocol]; ok { return protocol } // convert to int, look for that value @@ -967,7 +967,7 @@ func protocolForValue(v string) string { return protocol } - for k, v := range protocolIntegers() { + for k, v := range sgProtocolIntegers() { if p == v { // guard against protocolIntegers sometime in the future not having lower // case ids in the map @@ -980,6 +980,23 @@ func protocolForValue(v string) string { return protocol } +// a map of protocol names and their codes, defined at +// https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml, +// documented to be supported by AWS Security Groups +// http://docs.aws.amazon.com/fr_fr/AWSEC2/latest/APIReference/API_IpPermission.html +// Similar to protocolIntegers() used by Network ACLs, but explicitly only +// supports "tcp", "udp", "icmp", and "all" +func sgProtocolIntegers() map[string]int { + var protocolIntegers = make(map[string]int) + protocolIntegers = map[string]int{ + "udp": 17, + "tcp": 6, + "icmp": 1, + "all": -1, + } + return protocolIntegers +} + // The AWS Lambda service creates ENIs behind the scenes and keeps these around for a while // which would prevent SGs attached to such ENIs from being destroyed func deleteLingeringLambdaENIs(conn *ec2.EC2, d *schema.ResourceData) error { From c307dc95571f210931fda3c6aa1f59816f4ada41 Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Sat, 1 Oct 2016 00:35:27 +0200 Subject: [PATCH 12/16] Accept both slices and strings in vault_json (#9114) Fixes #9105 by allowing the `vault_json` to contain either slices or strings. And fixes #8932 by changing to way we cleanup the user key. --- .../provisioners/chef/resource_provisioner.go | 56 +++++--- .../chef/resource_provisioner_test.go | 125 ++++++++++++++++++ 2 files changed, 166 insertions(+), 15 deletions(-) diff --git a/builtin/provisioners/chef/resource_provisioner.go b/builtin/provisioners/chef/resource_provisioner.go index cf767c765..036e6af70 100644 --- a/builtin/provisioners/chef/resource_provisioner.go +++ b/builtin/provisioners/chef/resource_provisioner.go @@ -11,6 +11,7 @@ import ( "path" "regexp" "strings" + "sync" "text/template" "time" @@ -110,7 +111,7 @@ type Provisioner struct { Version string `mapstructure:"version"` attributes map[string]interface{} - vaults map[string]string + vaults map[string][]string cleanupUserKeyCmd string createConfigFiles func(terraform.UIOutput, communicator.Communicator) error @@ -192,12 +193,14 @@ func (r *ResourceProvisioner) Apply( defer comm.Disconnect() // Make sure we always delete the user key from the new node! - defer func() { + var once sync.Once + cleanupUserKey := func() { o.Output("Cleanup user key...") if err := p.runCommand(o, comm, p.cleanupUserKeyCmd); err != nil { o.Output("WARNING: Failed to cleanup user key on new node: " + err.Error()) } - }() + } + defer once.Do(cleanupUserKey) if !p.SkipInstall { if err := p.installChefClient(o, comm); err != nil { @@ -229,6 +232,10 @@ func (r *ResourceProvisioner) Apply( } } + // Cleanup the user key before we run Chef-Client to prevent issues + // with rights caused by changing settings during the run. + once.Do(cleanupUserKey) + o.Output("Starting initial Chef-Client run...") if err := p.runChefClient(o, comm); err != nil { return err @@ -352,11 +359,28 @@ func (r *ResourceProvisioner) decodeConfig(c *terraform.ResourceConfig) (*Provis } if vaults, ok := c.Config["vault_json"].(string); ok { - var m map[string]string + var m map[string]interface{} if err := json.Unmarshal([]byte(vaults), &m); err != nil { return nil, fmt.Errorf("Error parsing vault_json: %v", err) } - p.vaults = m + + v := make(map[string][]string) + for vault, items := range m { + switch items := items.(type) { + case []interface{}: + for _, item := range items { + if item, ok := item.(string); ok { + v[vault] = append(v[vault], item) + } + } + case interface{}: + if item, ok := items.(string); ok { + v[vault] = append(v[vault], item) + } + } + } + + p.vaults = v } return p, nil @@ -544,16 +568,18 @@ func (p *Provisioner) configureVaultsFunc( path.Join(confDir, p.UserName+".pem"), ) - for vault, item := range p.vaults { - updateCmd := fmt.Sprintf("%s vault update %s %s -A %s -M client %s", - knifeCmd, - vault, - item, - p.NodeName, - options, - ) - if err := p.runCommand(o, comm, updateCmd); err != nil { - return err + for vault, items := range p.vaults { + for _, item := range items { + updateCmd := fmt.Sprintf("%s vault update %s %s -A %s -M client %s", + knifeCmd, + vault, + item, + p.NodeName, + options, + ) + if err := p.runCommand(o, comm, updateCmd); err != nil { + return err + } } } diff --git a/builtin/provisioners/chef/resource_provisioner_test.go b/builtin/provisioners/chef/resource_provisioner_test.go index 8d9603f98..692c89f92 100644 --- a/builtin/provisioners/chef/resource_provisioner_test.go +++ b/builtin/provisioners/chef/resource_provisioner_test.go @@ -221,3 +221,128 @@ func TestResourceProvider_fetchChefCertificates(t *testing.T) { } } } + +func TestResourceProvider_configureVaults(t *testing.T) { + cases := map[string]struct { + Config *terraform.ResourceConfig + GemCmd string + KnifeCmd string + ConfDir string + Commands map[string]bool + }{ + "Linux Vault string": { + Config: testConfig(t, map[string]interface{}{ + "node_name": "nodename1", + "prevent_sudo": true, + "run_list": []interface{}{"cookbook::recipe"}, + "server_url": "https://chef.local", + "user_name": "bob", + "user_key": "USER-KEY", + "vault_json": `{"vault1": "item1"}`, + }), + + GemCmd: linuxGemCmd, + KnifeCmd: linuxKnifeCmd, + ConfDir: linuxConfDir, + + Commands: map[string]bool{ + fmt.Sprintf("%s install chef-vault", linuxGemCmd): true, + fmt.Sprintf("%s vault update vault1 item1 -A nodename1 -M client -c %s/client.rb "+ + "-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true, + }, + }, + + "Linux Vault []string": { + Config: testConfig(t, map[string]interface{}{ + "fetch_chef_certificates": true, + "node_name": "nodename1", + "prevent_sudo": true, + "run_list": []interface{}{"cookbook::recipe"}, + "server_url": "https://chef.local", + "user_name": "bob", + "user_key": "USER-KEY", + "vault_json": `{"vault1": ["item1", "item2"]}`, + }), + + GemCmd: linuxGemCmd, + KnifeCmd: linuxKnifeCmd, + ConfDir: linuxConfDir, + + Commands: map[string]bool{ + fmt.Sprintf("%s install chef-vault", linuxGemCmd): true, + fmt.Sprintf("%s vault update vault1 item1 -A nodename1 -M client -c %s/client.rb "+ + "-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true, + fmt.Sprintf("%s vault update vault1 item2 -A nodename1 -M client -c %s/client.rb "+ + "-u bob --key %s/bob.pem", linuxKnifeCmd, linuxConfDir, linuxConfDir): true, + }, + }, + + "Windows Vault string": { + Config: testConfig(t, map[string]interface{}{ + "node_name": "nodename1", + "prevent_sudo": true, + "run_list": []interface{}{"cookbook::recipe"}, + "server_url": "https://chef.local", + "user_name": "bob", + "user_key": "USER-KEY", + "vault_json": `{"vault1": "item1"}`, + }), + + GemCmd: windowsGemCmd, + KnifeCmd: windowsKnifeCmd, + ConfDir: windowsConfDir, + + Commands: map[string]bool{ + fmt.Sprintf("%s install chef-vault", windowsGemCmd): true, + fmt.Sprintf("%s vault update vault1 item1 -A nodename1 -M client -c %s/client.rb "+ + "-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true, + }, + }, + + "Windows Vault []string": { + Config: testConfig(t, map[string]interface{}{ + "fetch_chef_certificates": true, + "node_name": "nodename1", + "prevent_sudo": true, + "run_list": []interface{}{"cookbook::recipe"}, + "server_url": "https://chef.local", + "user_name": "bob", + "user_key": "USER-KEY", + "vault_json": `{"vault1": ["item1", "item2"]}`, + }), + + GemCmd: windowsGemCmd, + KnifeCmd: windowsKnifeCmd, + ConfDir: windowsConfDir, + + Commands: map[string]bool{ + fmt.Sprintf("%s install chef-vault", windowsGemCmd): true, + fmt.Sprintf("%s vault update vault1 item1 -A nodename1 -M client -c %s/client.rb "+ + "-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true, + fmt.Sprintf("%s vault update vault1 item2 -A nodename1 -M client -c %s/client.rb "+ + "-u bob --key %s/bob.pem", windowsKnifeCmd, windowsConfDir, windowsConfDir): true, + }, + }, + } + + r := new(ResourceProvisioner) + o := new(terraform.MockUIOutput) + c := new(communicator.MockCommunicator) + + for k, tc := range cases { + c.Commands = tc.Commands + + p, err := r.decodeConfig(tc.Config) + if err != nil { + t.Fatalf("Error: %v", err) + } + + p.configureVaults = p.configureVaultsFunc(tc.GemCmd, tc.KnifeCmd, tc.ConfDir) + p.useSudo = !p.PreventSudo + + err = p.configureVaults(o, c) + if err != nil { + t.Fatalf("Test %q failed: %v", k, err) + } + } +} From 628743b24c86c541b33f060f11b691e1c1f481b3 Mon Sep 17 00:00:00 2001 From: Sam Dunne Date: Thu, 29 Sep 2016 14:37:48 +0100 Subject: [PATCH 13/16] Add ability to skip chef registration This change allows a user to skip the bootstrap stage for a machine. --- .../provisioners/chef/resource_provisioner.go | 19 +++++++++++-------- .../docs/provisioners/chef.html.markdown | 6 +++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/builtin/provisioners/chef/resource_provisioner.go b/builtin/provisioners/chef/resource_provisioner.go index 036e6af70..0e693974e 100644 --- a/builtin/provisioners/chef/resource_provisioner.go +++ b/builtin/provisioners/chef/resource_provisioner.go @@ -104,6 +104,7 @@ type Provisioner struct { SecretKey string `mapstructure:"secret_key"` ServerURL string `mapstructure:"server_url"` SkipInstall bool `mapstructure:"skip_install"` + SkipRegister bool `mapstructure:"skip_register"` SSLVerifyMode string `mapstructure:"ssl_verify_mode"` UserName string `mapstructure:"user_name"` UserKey string `mapstructure:"user_key"` @@ -213,18 +214,20 @@ func (r *ResourceProvisioner) Apply( return err } - if p.FetchChefCertificates { - o.Output("Fetch Chef certificates...") - if err := p.fetchChefCertificates(o, comm); err != nil { + if !p.SkipRegister { + if p.FetchChefCertificates { + o.Output("Fetch Chef certificates...") + if err := p.fetchChefCertificates(o, comm); err != nil { + return err + } + } + + o.Output("Generate the private key...") + if err := p.generateClientKey(o, comm); err != nil { return err } } - o.Output("Generate the private key...") - if err := p.generateClientKey(o, comm); err != nil { - return err - } - if p.VaultJSON != "" { o.Output("Configure Chef vaults...") if err := p.configureVaults(o, comm); err != nil { diff --git a/website/source/docs/provisioners/chef.html.markdown b/website/source/docs/provisioners/chef.html.markdown index 00908a6f6..1bff3985a 100644 --- a/website/source/docs/provisioners/chef.html.markdown +++ b/website/source/docs/provisioners/chef.html.markdown @@ -115,13 +115,17 @@ The following arguments are supported: machine. This assumes Chef Client is already installed when you run the `chef` provisioner. +* `skip_register (boolean)` - (Optional) Skip the registration of Chef Client on the remote + machine. This assumes Chef Client is already registered when you run the `chef` + provisioner. + * `ssl_verify_mode (string)` - (Optional) Use to set the verify mode for Chef Client HTTPS requests. * `user_name (string)` - (Required) The name of an existing Chef user to use for registering the new Chef Client and (optionally) configure Chef Vaults. -* `user_key (string)` - (Required) The contents of the user key that will be used to +* `user_key (string)` - (Required) The contents of the user key that will be used to authenticate with the Chef Server. This can be loaded from a file on disk using the [`file()` interpolation function](/docs/configuration/interpolation.html#file_path_). From ef4d8dd4e233d3456d03be7e9b73c24f00a1c8be Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Sat, 1 Oct 2016 08:49:34 +0200 Subject: [PATCH 14/16] Update CHANGELOG.md --- CHANGELOG.md | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b441a417f..2486b07dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,25 +11,26 @@ IMPROVEMENTS: * provider/aws: Add JSON validation to the `aws_cloudwatch_event_rule` resource [GH-8897] * provider/aws: S3 bucket policies are imported as separate resources [GH-8915] * provider/aws: S3 bucket policies can now be removed via the `aws_s3_bucket` resource [GH-8915] - * provider/aws: Added a cluster_address attribute to aws elasticache [GH-8935] - * provider/aws: Add JSON validation to the aws_elasticsearch_domain resource. [GH-8898] - * provider/aws: Add JSON validation to the aws_kms_key resource. [GH-8900] - * provider/aws: Add JSON validation to the aws_s3_bucket_policy resource. [GH-8901] - * provider/aws: Add JSON validation to the aws_sns_topic resource. [GH-8902] - * provider/aws: Add JSON validation to the aws_sns_topic_policy resource. [GH-8903] - * provider/aws: Add JSON validation to the aws_sqs_queue resource. [GH-8904] - * provider/aws: Add JSON validation to the aws_sqs_queue_policy resource. [GH-8905] - * provider/aws: Add JSON validation to the aws_vpc_endpoint resource. [GH-8906] - * provider/aws: Update aws_cloudformation_stack data source with new helper function. [GH-8907] - * provider/aws: Add JSON validation to the aws_s3_bucket resource. [GH-8908] + * provider/aws: Added a `cluster_address` attribute to aws elasticache [GH-8935] + * provider/aws: Add JSON validation to the `aws_elasticsearch_domain resource`. [GH-8898] + * provider/aws: Add JSON validation to the `aws_kms_key resource`. [GH-8900] + * provider/aws: Add JSON validation to the `aws_s3_bucket_policy resource`. [GH-8901] + * provider/aws: Add JSON validation to the `aws_sns_topic resource`. [GH-8902] + * provider/aws: Add JSON validation to the `aws_sns_topic_policy resource`. [GH-8903] + * provider/aws: Add JSON validation to the `aws_sqs_queue resource`. [GH-8904] + * provider/aws: Add JSON validation to the `aws_sqs_queue_policy resource`. [GH-8905] + * provider/aws: Add JSON validation to the `aws_vpc_endpoint resource`. [GH-8906] + * provider/aws: Update `aws_cloudformation_stack` data source with new helper function. [GH-8907] + * provider/aws: Add JSON validation to the `aws_s3_bucket` resource. [GH-8908] * provider/aws: Add support for `cloudwatch_logging_options` to Firehose Delivery Streams [GH-8671] * provider/aws: Add HTTP/2 support via the http_version parameter to CloudFront distribution [GH-8777] - * provider/aws: Add query_string_cache_keys to allow for selective caching of CloudFront keys [GH-8777] - * provider/aws: Support Import aws_elasticache_cluster [GH-9010] - * provider/aws: Add support for tags to aws_cloudfront_distribution [GH-9011] + * provider/aws: Add `query_string_cache_keys` to allow for selective caching of CloudFront keys [GH-8777] + * provider/aws: Support Import `aws_elasticache_cluster` [GH-9010] + * provider/aws: Add support for tags to `aws_cloudfront_distribution` [GH-9011] * provider/azurerm: Add normalizeJsonString and validateJsonString functions [GH-8909] * provider/openstack: Use proxy environment variables for communication with services [GH-8948] - * provider/vsphere: Adding 'detach_unknown_disks_on_delete' flag for VM resource [GH-8947] + * provider/vsphere: Adding `detach_unknown_disks_on_delete` flag for VM resource [GH-8947] + * provisioner/chef: Add `skip_register` attribute to allow skipping the registering steps [GH-9127] BUG FIXES: * core: Fixed variables not being in scope for destroy -target on modules [GH-9021] @@ -53,7 +54,8 @@ BUG FIXES: * provider/aws: Modifying the parameter_group_name of aws_elasticache_replication_group caused a panic [GH-9101] * provider/aws: Fix issue with updating ELB subnets for subnets in the same AZ [GH-9131] * provider/librato: Mandatory name and conditions attributes weren't being sent on Update unless changed [GH-8984] - + * provisioner/chef: Fix an error with parsing certain `vault_json` content [GH-9114] + * provisioner/chef: Change to order in which to cleanup the user key so this is done before the Chef run starts [GH-9114] ## 0.7.4 (September 19, 2016) From 59b67efd8a9b37242e2dca10065d6a365aa24454 Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Sat, 1 Oct 2016 09:43:23 +0200 Subject: [PATCH 15/16] provisioner/chef: make docs a little more explicit (#9159) --- website/source/docs/provisioners/chef.html.markdown | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/source/docs/provisioners/chef.html.markdown b/website/source/docs/provisioners/chef.html.markdown index 1bff3985a..fed9eb21c 100644 --- a/website/source/docs/provisioners/chef.html.markdown +++ b/website/source/docs/provisioners/chef.html.markdown @@ -116,7 +116,8 @@ The following arguments are supported: provisioner. * `skip_register (boolean)` - (Optional) Skip the registration of Chef Client on the remote - machine. This assumes Chef Client is already registered when you run the `chef` + machine. This assumes Chef Client is already registered and the private key (`client.pem`) + is available in the default Chef configuration directory when you run the `chef` provisioner. * `ssl_verify_mode (string)` - (Optional) Use to set the verify mode for Chef Client HTTPS From 93308a2b368886e9e7b06d8baf9a8e7697e5b74e Mon Sep 17 00:00:00 2001 From: James Turnbull Date: Sat, 1 Oct 2016 10:32:46 -0400 Subject: [PATCH 16/16] Update of the module creation page Updated some style, grammar and formatting. --- .../source/docs/modules/create.html.markdown | 80 +++++-------------- 1 file changed, 22 insertions(+), 58 deletions(-) diff --git a/website/source/docs/modules/create.html.markdown b/website/source/docs/modules/create.html.markdown index 05669ff78..0fa50e872 100644 --- a/website/source/docs/modules/create.html.markdown +++ b/website/source/docs/modules/create.html.markdown @@ -2,31 +2,21 @@ layout: "docs" page_title: "Creating Modules" sidebar_current: "docs-modules-create" -description: |- - Creating modules in Terraform is easy. You may want to do this to better organize your code, to make a reusable component, or just to learn more about Terraform. For any reason, if you already know the basics of Terraform, creating a module is a piece of cake. +description: How to create modules. --- # Creating Modules -Creating modules in Terraform is easy. You may want to do this to better -organize your code, to make a reusable component, or just to learn more about -Terraform. For any reason, if you already know the basics of Terraform, -creating a module is a piece of cake. +Creating modules in Terraform is easy. You may want to do this to better organize your code, to make a reusable component, or just to learn more about Terraform. For any reason, if you already know the basics of Terraform, then creating a module is a piece of cake. -Modules in Terraform are just folders with Terraform files. In fact, -when you run `terraform apply`, the current working directory holding -the Terraform files you're applying comprise what is called the -_root module_. It itself is a valid module. +Modules in Terraform are folders with Terraform files. In fact, when you run `terraform apply`, the current working directory holding +the Terraform files you're applying comprise what is called the _root module_. This itself is a valid module. -Therefore, you can enter the source of any module, run `terraform apply`, -and expect it to work (assuming you satisfy the required variables, if any). +Therefore, you can enter the source of any module, satisfy any required variables, run `terraform apply`, and expect it to work. -## An Example +## An Example Module -Within a folder containing Terraform configurations, create a subfolder -"child". In this subfolder, make one empty "main.tf" file. Then, back in -the root folder containing the "child" folder, add this to one of the -Terraform files: +Within a folder containing Terraform configurations, create a subfolder called `child`. In this subfolder, make one empty `main.tf` file. Then, back in the root folder containing the `child` folder, add this to one of your Terraform configuration files: ``` module "child" { @@ -34,25 +24,18 @@ module "child" { } ``` -This will work. You've created your first module! You can add resources -to the child module to see how that interaction works. +You've now created your first module! You can now add resources to the `child` module. -Note: Prior to running the above, you'll have to run -[the get command](/docs/commands/get.html) for Terraform to sync -your modules. This should be instant since the module is just a local path. +**Note:** Prior to running the above, you'll have to run [the get command](/docs/commands/get.html) for Terraform to sync +your modules. This should be instant since the module is a local path. ## Inputs/Outputs -To make modules more useful than simple isolated containers of Terraform -configurations, modules can be configured and also have outputs that can be -consumed by the configuration using the module. +To make modules more useful than simple isolated containers of Terraform configurations, modules can be configured and also have outputs that can be consumed by your Terraform configuration. -Inputs of a module are [variables](/docs/configuration/variables.html) -and outputs are [outputs](/docs/configuration/outputs.html). There is no -special syntax to define these, they're defined just like any other -variables or outputs. +Inputs of a module are [variables](/docs/configuration/variables.html) and outputs are [outputs](/docs/configuration/outputs.html). There is no special syntax to define these, they're defined just like any other variables or outputs. You can think about these variables and outputs as the API interface to your module. -In the "child" module we created above, add the following: +Let's add a variable and an output to our `child` module. ``` variable "memory" {} @@ -62,8 +45,7 @@ output "received" { } ``` -This will create a required variable "memory" and then an output "received" -that will simply be the value of the memory variable. +This will create a required variable, `memory`, and then an output, `received`, that will be the value of the `memory` variable. You can then configure the module and use the output like so: @@ -79,24 +61,13 @@ output "child_memory" { } ``` -If you run `apply`, you'll again see that this works. - -And that is all there is to it. Variables and outputs are used to configure -modules and provide results. Resources within a module are isolated, -and the whole thing is managed as a single unit. +If you now run `terraform apply`, you see how this works. ## Paths and Embedded Files -It is sometimes useful to embed files within the module that aren't -Terraform configuration files, such as a script to provision a resource -or a file to upload. +It is sometimes useful to embed files within the module that aren't Terraform configuration files, such as a script to provision a resource or a file to upload. -In these cases, you can't use a relative path, since paths in Terraform -are generally relative to the working directory that Terraform was executed -from. Instead, you want to use a module-relative path. To do this, use -the [path interpolated variables](/docs/configuration/interpolation.html). - -An example is shown below: +In these cases, you can't use a relative path, since paths in Terraform are generally relative to the working directory from which Terraform was executed. Instead, you want to use a module-relative path. To do this, you should use the [path interpolated variables](/docs/configuration/interpolation.html). ``` resource "aws_instance" "server" { @@ -108,20 +79,13 @@ resource "aws_instance" "server" { } ``` -In the above, we use `${path.module}` to get a module-relative path. This -is usually what you'll want in any case. +Here we use `${path.module}` to get a module-relative path. ## Nested Modules -You can use a module within a module just like you would anywhere else. -This module will be hidden from the root user, so you'll have re-expose any -variables if you need to, as well as outputs. +You can nest a module within another module. This module will be hidden from your root configuration, so you'll have re-expose any +variables and outputs you require. -The [get command](/docs/commands/get.html) will automatically get all -nested modules as well. +The [get command](/docs/commands/get.html) will automatically get all nested modules. -You don't have to worry about conflicting versions of modules, since -Terraform builds isolated subtrees of all dependencies. For example, -one module might use version 1.0 of module "foo" and another module -might use version 2.0 of module "foo", and this would all work fine -within Terraform since the modules are created separately. +You don't have to worry about conflicting versions of modules, since Terraform builds isolated subtrees of all dependencies. For example, one module might use version 1.0 of module `foo` and another module might use version 2.0, and this will all work fine within Terraform since the modules are created separately.