From 967a688f225249117b4f373e2f17e0a9115d81fc Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 5 Apr 2018 15:09:09 -0400 Subject: [PATCH 01/15] update travis to go1.10.1 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c11f41424..06ad5da2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ dist: trusty sudo: false language: go go: -- "1.10" +- "1.10.1" # add TF_CONSUL_TEST=1 to run consul tests # they were causing timouts in travis From 58c4504148056670a748d7d8bd38635264bef76f Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 5 Apr 2018 19:42:26 +0000 Subject: [PATCH 02/15] release: clean up after v0.11.6 --- CHANGELOG.md | 2 ++ version/version.go | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a2d44168..a2115140e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.11.7 (Unreleased) + ## 0.11.6 (April 5, 2018) BUG FIXES: diff --git a/version/version.go b/version/version.go index b7decd1f1..6693b0e1c 100644 --- a/version/version.go +++ b/version/version.go @@ -11,12 +11,12 @@ import ( ) // The main version number that is being run at the moment. -const Version = "0.11.6" +const Version = "0.11.7" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. -var Prerelease = "" +var Prerelease = "dev" // SemVer is an instance of version.Version. This has the secondary // benefit of verifying during tests and init time that our version is a From fdbd15344977408875bfbcb931893002db27352d Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 5 Apr 2018 16:14:55 -0400 Subject: [PATCH 03/15] update CHANGELOG.md Fix link formatting from script Add missing entry --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2115140e..d4c784820 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ BUG FIXES: * connection/ssh: Retry on authentication failures when the remote service is available before it is completely configured ([#17744](https://github.com/hashicorp/terraform/issues/17744)) * connection/winrm: Get execution errors from winrm commands ([#17788](https://github.com/hashicorp/terraform/issues/17788)) * connection/winrm: Support NTLM authentication ([#17748](https://github.com/hashicorp/terraform/issues/17748)) -* provisioner/habitat: Set channel and builder URL during install, and enable service before start ([#17403](https://github.com/hashicorp/terraform/issues/17403)] [[#17781](https://github.com/hashicorp/terraform/issues/17781)) +* provisioner/chef: Fix regression causing connection to be prematurely closed ([#17609](https://github.com/hashicorp/terraform/pull/17609)) +* provisioner/habitat: Set channel and builder URL during install, and enable service before start ([#17403](https://github.com/hashicorp/terraform/issues/17403)) ([#17781](https://github.com/hashicorp/terraform/issues/17781)) PROVIDER SDK CHANGES (not user-facing): From d9b315564e0dd5a4de8fa1dd2418ea999e6e482b Mon Sep 17 00:00:00 2001 From: Andrew Bloomgarden Date: Fri, 6 Apr 2018 22:16:25 -0400 Subject: [PATCH 04/15] tools/terraform-bundle: compress files in the generated zip file The FileInfoHeader method does not compress files by default. --- tools/terraform-bundle/package.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/terraform-bundle/package.go b/tools/terraform-bundle/package.go index b21626aa5..82e43ee88 100644 --- a/tools/terraform-bundle/package.go +++ b/tools/terraform-bundle/package.go @@ -234,6 +234,7 @@ func (c *PackageCommand) Run(args []string) int { c.ui.Error(fmt.Sprintf("Failed to add zip entry for %s: %s", fn, err)) return 1 } + hdr.Method = zip.Deflate // be sure to compress files w, err := outZ.CreateHeader(hdr) if err != nil { c.ui.Error(fmt.Sprintf("Failed to add zip entry for %s: %s", fn, err)) From d7048cb640c53294df36283e297316751e113fcd Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Sat, 7 Apr 2018 13:06:47 -0700 Subject: [PATCH 05/15] helper/schema: ResourceDiff ForceNew attribute correctness A couple of bugs have been discovered in ResourceDiff.ForceNew: * NewRemoved is not preserved when a diff for a key is already present. This is because the second diff that happens after customization performs a second getChange on not just state and config, but also on the pre-existing diff. This results in Exists == true, meaning nil is never returned as a new value. * ForceNew was doing the work of adding the key to the list of changed keys by doing a full SetNew on the existing value. This has a side effect of fetching zero values from what were otherwise undefined values and creating diffs for these values where there should not have been (example: "" => "0"). This update fixes these scenarios by: * Adding a new private function to check the existing diff for NewRemoved keys. This is included in the check on new values in diffChange. * Keys that have been flagged as ForceNew (or parent keys of lists and sets that have been flagged as ForceNew) are now maintained in a separate map. UpdatedKeys now returns the results of both of these maps, but otherwise these keys are ignored by ResourceDiff. * Pursuant the above, values are no longer pushed into the newDiff writer by ForceNew. This prevents the zero value problem, and makes for a cleaner implementation where the provider has to "manually" SetNew to update the appropriate values in the writer. It also prevents non-computed keys from winding up in the diff, which ResourceDiff normally blocks by design. There are also a couple of tests for cases that should never come up right now involving Optional/Computed values and NewRemoved, for which explanations are given in annotations of each test. These are here to guard against future regressions. --- helper/schema/resource_diff.go | 38 +++++++- helper/schema/resource_diff_test.go | 134 ++++++++++++++++++++++++++++ helper/schema/schema_test.go | 42 +++++++++ 3 files changed, 210 insertions(+), 4 deletions(-) diff --git a/helper/schema/resource_diff.go b/helper/schema/resource_diff.go index 773c24cf7..92b891fc5 100644 --- a/helper/schema/resource_diff.go +++ b/helper/schema/resource_diff.go @@ -135,6 +135,10 @@ type ResourceDiff struct { // diff does not get re-run on keys that were not touched, or diffs that were // just removed (re-running on the latter would just roll back the removal). updatedKeys map[string]bool + + // Tracks which keys were flagged as forceNew. These keys are not saved in + // newWriter, but we need to track them so that they can be re-diffed later. + forcedNewKeys map[string]bool } // newResourceDiff creates a new ResourceDiff instance. @@ -193,17 +197,30 @@ func newResourceDiff(schema map[string]*Schema, config *terraform.ResourceConfig } d.updatedKeys = make(map[string]bool) + d.forcedNewKeys = make(map[string]bool) return d } // UpdatedKeys returns the keys that were updated by this ResourceDiff run. // These are the only keys that a diff should be re-calculated for. +// +// This is the combined result of both keys for which diff values were updated +// for or cleared, and also keys that were flagged to be re-diffed as a result +// of ForceNew. func (d *ResourceDiff) UpdatedKeys() []string { var s []string for k := range d.updatedKeys { s = append(s, k) } + for k := range d.forcedNewKeys { + for _, l := range s { + if k == l { + break + } + } + s = append(s, k) + } return s } @@ -257,7 +274,7 @@ func (d *ResourceDiff) diffChange(key string) (interface{}, interface{}, bool, b if !old.Exists { old.Value = nil } - if !new.Exists { + if !new.Exists || d.removed(key) { new.Value = nil } @@ -335,9 +352,12 @@ func (d *ResourceDiff) ForceNew(key string) error { schema.ForceNew = true - // We need to set whole lists/sets/maps here - _, new := d.GetChange(keyParts[0]) - return d.setDiff(keyParts[0], new, false) + // Flag this for a re-diff. Don't save any values to guarantee that existing + // diffs aren't messed with, as this gets messy when dealing with complex + // structures, zero values, etc. + d.forcedNewKeys[keyParts[0]] = true + + return nil } // Get hands off to ResourceData.Get. @@ -449,6 +469,16 @@ func (d *ResourceDiff) getChange(key string) (getResult, getResult, bool) { return old, new, false } +// removed checks to see if the key is present in the existing, pre-customized +// diff and if it was marked as NewRemoved. +func (d *ResourceDiff) removed(k string) bool { + diff, ok := d.diff.Attributes[k] + if !ok { + return false + } + return diff.NewRemoved +} + // get performs the appropriate multi-level reader logic for ResourceDiff, // starting at source. Refer to newResourceDiff for the level order. func (d *ResourceDiff) get(addr []string, source string) getResult { diff --git a/helper/schema/resource_diff_test.go b/helper/schema/resource_diff_test.go index 4345fac1e..fdb8937e5 100644 --- a/helper/schema/resource_diff_test.go +++ b/helper/schema/resource_diff_test.go @@ -553,6 +553,52 @@ func testDiffCases(t *testing.T, oldPrefix string, oldOffset int, computed bool) NewValue: "qux", ExpectedError: true, }, + resourceDiffTestCase{ + // NOTE: This case is technically impossible in the current + // implementation, because optional+computed values never show up in the + // diff, and we actually clear existing diffs when SetNew or + // SetNewComputed is run. This test is here to ensure that if either of + // these behaviors change that we don't introduce regressions. + Name: "NewRemoved in diff for Optional and Computed, should be fully overridden", + Schema: map[string]*Schema{ + "foo": &Schema{ + Type: TypeString, + Optional: true, + Computed: true, + }, + }, + State: &terraform.InstanceState{ + Attributes: map[string]string{ + "foo": "bar", + }, + }, + Config: testConfig(t, map[string]interface{}{}), + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "foo": &terraform.ResourceAttrDiff{ + Old: "bar", + New: "", + NewRemoved: true, + }, + }, + }, + Key: "foo", + NewValue: "qux", + Expected: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "foo": &terraform.ResourceAttrDiff{ + Old: "bar", + New: func() string { + if computed { + return "" + } + return "qux" + }(), + NewComputed: computed, + }, + }, + }, + }, } } @@ -765,6 +811,94 @@ func TestForceNew(t *testing.T) { }, }, }, + resourceDiffTestCase{ + Name: "preserve NewRemoved on existing diff", + Schema: map[string]*Schema{ + "foo": &Schema{ + Type: TypeString, + Optional: true, + }, + }, + State: &terraform.InstanceState{ + Attributes: map[string]string{ + "foo": "bar", + }, + }, + Config: testConfig(t, map[string]interface{}{}), + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "foo": &terraform.ResourceAttrDiff{ + Old: "bar", + New: "", + NewRemoved: true, + }, + }, + }, + Key: "foo", + Expected: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "foo": &terraform.ResourceAttrDiff{ + Old: "bar", + New: "", + RequiresNew: true, + NewRemoved: true, + }, + }, + }, + }, + resourceDiffTestCase{ + Name: "nested field, preserve original diff without zero values", + Schema: map[string]*Schema{ + "foo": &Schema{ + Type: TypeList, + Required: true, + MaxItems: 1, + Elem: &Resource{ + Schema: map[string]*Schema{ + "bar": { + Type: TypeString, + Optional: true, + }, + "baz": { + Type: TypeInt, + Optional: true, + }, + }, + }, + }, + }, + State: &terraform.InstanceState{ + Attributes: map[string]string{ + "foo.#": "1", + "foo.0.bar": "abc", + }, + }, + Config: testConfig(t, map[string]interface{}{ + "foo": []map[string]interface{}{ + map[string]interface{}{ + "bar": "abcdefg", + }, + }, + }), + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "foo.0.bar": &terraform.ResourceAttrDiff{ + Old: "abc", + New: "abcdefg", + }, + }, + }, + Key: "foo.0.bar", + Expected: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "foo.0.bar": &terraform.ResourceAttrDiff{ + Old: "abc", + New: "abcdefg", + RequiresNew: true, + }, + }, + }, + }, } for _, tc := range cases { t.Run(tc.Name, func(t *testing.T) { diff --git a/helper/schema/schema_test.go b/helper/schema/schema_test.go index 4b0d5afb8..820352aea 100644 --- a/helper/schema/schema_test.go +++ b/helper/schema/schema_test.go @@ -2866,6 +2866,48 @@ func TestSchemaMap_Diff(t *testing.T) { }, { + // NOTE: This case is technically impossible in the current + // implementation, because optional+computed values never show up in the + // diff. In the event behavior changes this test should ensure that the + // intended diff still shows up. + Name: "overridden removed attribute diff with a CustomizeDiff function, ForceNew not in schema", + Schema: map[string]*Schema{ + "availability_zone": &Schema{ + Type: TypeString, + Optional: true, + Computed: true, + }, + }, + + State: nil, + + Config: map[string]interface{}{}, + + CustomizeDiff: func(d *ResourceDiff, meta interface{}) error { + if err := d.SetNew("availability_zone", "bar"); err != nil { + return err + } + if err := d.ForceNew("availability_zone"); err != nil { + return err + } + return nil + }, + + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "availability_zone": &terraform.ResourceAttrDiff{ + Old: "", + New: "bar", + RequiresNew: true, + }, + }, + }, + + Err: false, + }, + + { + Name: "overridden diff with a CustomizeDiff function, ForceNew in schema", Schema: map[string]*Schema{ "availability_zone": &Schema{ From 36539f1a2589ab95cf9a7f833bf6ac255be3bc1c Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 9 Apr 2018 10:52:57 -0700 Subject: [PATCH 06/15] add VMware NSX-T links to provider index pages --- website/docs/providers/index.html.markdown | 5 +++++ website/docs/providers/type/major-index.html.markdown | 2 ++ 2 files changed, 7 insertions(+) diff --git a/website/docs/providers/index.html.markdown b/website/docs/providers/index.html.markdown index 868118ac6..d285df1e1 100644 --- a/website/docs/providers/index.html.markdown +++ b/website/docs/providers/index.html.markdown @@ -139,7 +139,12 @@ down to see all providers. Vault VMware vCloud Director + VMware NSX-T + + VMware vSphere + + diff --git a/website/docs/providers/type/major-index.html.markdown b/website/docs/providers/type/major-index.html.markdown index ab6200320..278287c88 100644 --- a/website/docs/providers/type/major-index.html.markdown +++ b/website/docs/providers/type/major-index.html.markdown @@ -31,4 +31,6 @@ tested by HashiCorp. [Oracle Public Cloud](/docs/providers/opc/index.html) +[VMware NSX-T](/docs/provider/nsxt/index.html) + [VMware vSphere](/docs/providers/vsphere/index.html) From 3ab13fefad6894a40de0f5a584bf4146e3869985 Mon Sep 17 00:00:00 2001 From: Chris Griggs Date: Mon, 9 Apr 2018 11:05:36 -0700 Subject: [PATCH 07/15] Fix typo --- website/docs/providers/index.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/providers/index.html.markdown b/website/docs/providers/index.html.markdown index d285df1e1..8f8a4fdd1 100644 --- a/website/docs/providers/index.html.markdown +++ b/website/docs/providers/index.html.markdown @@ -139,7 +139,7 @@ down to see all providers. Vault VMware vCloud Director - VMware NSX-T + VMware NSX-T VMware vSphere From b0f0dd27955caffbe1cac4ca5d6833bcb65ceec6 Mon Sep 17 00:00:00 2001 From: Chris Griggs Date: Mon, 9 Apr 2018 11:06:06 -0700 Subject: [PATCH 08/15] fix typo --- website/docs/providers/type/major-index.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/providers/type/major-index.html.markdown b/website/docs/providers/type/major-index.html.markdown index 278287c88..c6dd892dc 100644 --- a/website/docs/providers/type/major-index.html.markdown +++ b/website/docs/providers/type/major-index.html.markdown @@ -31,6 +31,6 @@ tested by HashiCorp. [Oracle Public Cloud](/docs/providers/opc/index.html) -[VMware NSX-T](/docs/provider/nsxt/index.html) +[VMware NSX-T](/docs/providers/nsxt/index.html) [VMware vSphere](/docs/providers/vsphere/index.html) From 76974209ec706948aea2f7cb17df518f6f28bae0 Mon Sep 17 00:00:00 2001 From: Clint Date: Mon, 9 Apr 2018 15:11:59 -0500 Subject: [PATCH 09/15] Update guides.erb Update "Writing Custom Providers" guide link to new Extend section --- website/layouts/guides.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/layouts/guides.erb b/website/layouts/guides.erb index e1bc649c8..9c5944fa8 100644 --- a/website/layouts/guides.erb +++ b/website/layouts/guides.erb @@ -18,7 +18,7 @@ > - Writing Custom Providers + Writing Custom Providers > Running Terraform in Automation From 0e357e56ed9fd3e5d02f5486b127a0bf2ea86e59 Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Mon, 9 Apr 2018 15:57:03 -0700 Subject: [PATCH 10/15] Update CHANGELOG.md --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4c784820..ce7420447 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ ## 0.11.7 (Unreleased) +PROVIDER SDK CHANGES (not user-facing): + +* helper/schema: Invoking `ForceNew` on a key being removed from config during + diff customization now correctly exposes that key as being removed in the + updated diff. This prevents diff mismatches under certain circumstances. + [GH-17811] +* helper/schema: Invoking `ForceNew` on its own no longer writes any new data to + the diff. This prevents writing of new nil to zero value diffs for sub-fields + of complex lists and sets where a diff did not exist before. [GH-17811] + ## 0.11.6 (April 5, 2018) BUG FIXES: From be6fffb1719d31f33f020501b049e0740284ce04 Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Mon, 9 Apr 2018 15:58:12 -0700 Subject: [PATCH 11/15] Add a little more explanation for GH-17811 in CHANGELOG.md --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce7420447..e521f2964 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,10 @@ PROVIDER SDK CHANGES (not user-facing): diff customization now correctly exposes that key as being removed in the updated diff. This prevents diff mismatches under certain circumstances. [GH-17811] -* helper/schema: Invoking `ForceNew` on its own no longer writes any new data to - the diff. This prevents writing of new nil to zero value diffs for sub-fields - of complex lists and sets where a diff did not exist before. [GH-17811] +* helper/schema: Invoking `ForceNew` during diff customization on its own no + longer writes any new data to the diff. This prevents writing of new nil to + zero value diffs for sub-fields of complex lists and sets where a diff did not + exist before. [GH-17811] ## 0.11.6 (April 5, 2018) From cfefeec9260146313833e867df18541c2bca0a78 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 10 Apr 2018 11:32:52 -0400 Subject: [PATCH 12/15] walkDestroy is a form of "apply" When computing the count value, make sure to include walkDestroy with walkApply, as the former is only a special case of the latter. When applying a saved plan, the computed count values are lost and we can no longer query the state for those values. The apply walk was already considered in the `resourceCountMax` function, but the destroy walk was not. This worked when destroying in a single operation ("terraform destroy"), since the state would still be updated with the latest counts from the plan. --- terraform/context_apply_test.go | 83 +++++++++++++++++++ terraform/interpolate.go | 3 +- .../plan-destroy-interpolated-count/main.tf | 11 +++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 terraform/test-fixtures/plan-destroy-interpolated-count/main.tf diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index 8da5b720e..9bea9b1ab 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -9578,6 +9578,89 @@ func TestContext2Apply_plannedInterpolatedCount(t *testing.T) { } } +func TestContext2Apply_plannedDestroyInterpolatedCount(t *testing.T) { + m := testModule(t, "plan-destroy-interpolated-count") + + p := testProvider("aws") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + + providerResolver := ResourceProviderResolverFixed( + map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + ) + + s := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "aws_instance.a.0": { + Type: "aws_instance", + Primary: &InstanceState{ + ID: "foo", + }, + Provider: "provider.aws", + }, + "aws_instance.a.1": { + Type: "aws_instance", + Primary: &InstanceState{ + ID: "foo", + }, + Provider: "provider.aws", + }, + }, + Outputs: map[string]*OutputState{ + "out": { + Type: "list", + Value: []string{"foo", "foo"}, + }, + }, + }, + }, + } + + ctx := testContext2(t, &ContextOpts{ + Module: m, + ProviderResolver: providerResolver, + State: s, + Destroy: true, + }) + + plan, err := ctx.Plan() + if err != nil { + t.Fatalf("plan failed: %s", err) + } + + // We'll marshal and unmarshal the plan here, to ensure that we have + // a clean new context as would be created if we separately ran + // terraform plan -out=tfplan && terraform apply tfplan + var planBuf bytes.Buffer + err = WritePlan(plan, &planBuf) + if err != nil { + t.Fatalf("failed to write plan: %s", err) + } + plan, err = ReadPlan(&planBuf) + if err != nil { + t.Fatalf("failed to read plan: %s", err) + } + + ctx, err = plan.Context(&ContextOpts{ + ProviderResolver: providerResolver, + Destroy: true, + }) + if err != nil { + t.Fatalf("failed to create context for plan: %s", err) + } + + // Applying the plan should now succeed + _, err = ctx.Apply() + if err != nil { + t.Fatalf("apply failed: %s", err) + } +} + func TestContext2Apply_scaleInMultivarRef(t *testing.T) { m := testModule(t, "apply-resource-scale-in") diff --git a/terraform/interpolate.go b/terraform/interpolate.go index f3d9adefe..4f4e178cf 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -789,7 +789,8 @@ func (i *Interpolater) resourceCountMax( // If we're NOT applying, then we assume we can read the count // from the state. Plan and so on may not have any state yet so // we do a full interpolation. - if i.Operation != walkApply { + // Don't forget walkDestroy, which is a special case of walkApply + if !(i.Operation == walkApply || i.Operation == walkDestroy) { if cr == nil { return 0, nil } diff --git a/terraform/test-fixtures/plan-destroy-interpolated-count/main.tf b/terraform/test-fixtures/plan-destroy-interpolated-count/main.tf new file mode 100644 index 000000000..b4ef77aba --- /dev/null +++ b/terraform/test-fixtures/plan-destroy-interpolated-count/main.tf @@ -0,0 +1,11 @@ +variable "list" { + default = ["1", "2"] +} + +resource "aws_instance" "a" { + count = "${length(var.list)}" +} + +output "out" { + value = "${aws_instance.a.*.id}" +} From 08f32443fc9336247e570b74777133af1e8b6905 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 10 Apr 2018 12:03:44 -0400 Subject: [PATCH 13/15] update go-getter update to the latest version of go-getter --- .../github.com/hashicorp/go-getter/README.md | 5 +- .../github.com/hashicorp/go-getter/client.go | 23 +- .../hashicorp/go-getter/decompress.go | 25 ++ .../hashicorp/go-getter/decompress_tar.go | 28 +- .../hashicorp/go-getter/decompress_testing.go | 25 ++ .../hashicorp/go-getter/decompress_zip.go | 5 + .../github.com/hashicorp/go-getter/get_git.go | 7 +- .../github.com/hashicorp/go-getter/get_hg.go | 10 +- .../hashicorp/go-getter/get_http.go | 23 +- .../github.com/hashicorp/go-safetemp/LICENSE | 362 ++++++++++++++++++ .../hashicorp/go-safetemp/README.md | 10 + .../hashicorp/go-safetemp/safetemp.go | 40 ++ vendor/vendor.json | 12 +- 13 files changed, 544 insertions(+), 31 deletions(-) create mode 100644 vendor/github.com/hashicorp/go-safetemp/LICENSE create mode 100644 vendor/github.com/hashicorp/go-safetemp/README.md create mode 100644 vendor/github.com/hashicorp/go-safetemp/safetemp.go diff --git a/vendor/github.com/hashicorp/go-getter/README.md b/vendor/github.com/hashicorp/go-getter/README.md index a9eafd61f..40ace74d8 100644 --- a/vendor/github.com/hashicorp/go-getter/README.md +++ b/vendor/github.com/hashicorp/go-getter/README.md @@ -232,6 +232,9 @@ The options below are available to all protocols: * `checksum` - Checksum to verify the downloaded file or archive. See the entire section on checksumming above for format and more details. + * `filename` - When in file download mode, allows specifying the name of the + downloaded file on disk. Has no effect in directory mode. + ### Local Files (`file`) None @@ -282,7 +285,7 @@ be used automatically. * `aws_access_key_id` (required) - Minio access key. * `aws_access_key_secret` (required) - Minio access key secret. * `region` (optional - defaults to us-east-1) - Region identifier to use. - * `version` (optional - fefaults to Minio default) - Configuration file format. + * `version` (optional - defaults to Minio default) - Configuration file format. #### S3 Bucket Examples diff --git a/vendor/github.com/hashicorp/go-getter/client.go b/vendor/github.com/hashicorp/go-getter/client.go index b67bb641c..300301c2e 100644 --- a/vendor/github.com/hashicorp/go-getter/client.go +++ b/vendor/github.com/hashicorp/go-getter/client.go @@ -17,6 +17,7 @@ import ( "strings" urlhelper "github.com/hashicorp/go-getter/helper/url" + "github.com/hashicorp/go-safetemp" ) // Client is a client for downloading things. @@ -100,17 +101,14 @@ func (c *Client) Get() error { dst := c.Dst src, subDir := SourceDirSubdir(src) if subDir != "" { - tmpDir, err := ioutil.TempDir("", "tf") + td, tdcloser, err := safetemp.Dir("", "getter") if err != nil { return err } - if err := os.RemoveAll(tmpDir); err != nil { - return err - } - defer os.RemoveAll(tmpDir) + defer tdcloser.Close() realDst = dst - dst = tmpDir + dst = td } u, err := urlhelper.Parse(src) @@ -232,7 +230,18 @@ func (c *Client) Get() error { // Destination is the base name of the URL path in "any" mode when // a file source is detected. if mode == ClientModeFile { - dst = filepath.Join(dst, filepath.Base(u.Path)) + filename := filepath.Base(u.Path) + + // Determine if we have a custom file name + if v := q.Get("filename"); v != "" { + // Delete the query parameter if we have it. + q.Del("filename") + u.RawQuery = q.Encode() + + filename = v + } + + dst = filepath.Join(dst, filename) } } diff --git a/vendor/github.com/hashicorp/go-getter/decompress.go b/vendor/github.com/hashicorp/go-getter/decompress.go index fc5681d39..198bb0edd 100644 --- a/vendor/github.com/hashicorp/go-getter/decompress.go +++ b/vendor/github.com/hashicorp/go-getter/decompress.go @@ -1,7 +1,15 @@ package getter +import ( + "strings" +) + // Decompressor defines the interface that must be implemented to add // support for decompressing a type. +// +// Important: if you're implementing a decompressor, please use the +// containsDotDot helper in this file to ensure that files can't be +// decompressed outside of the specified directory. type Decompressor interface { // Decompress should decompress src to dst. dir specifies whether dst // is a directory or single file. src is guaranteed to be a single file @@ -31,3 +39,20 @@ func init() { "zip": new(ZipDecompressor), } } + +// containsDotDot checks if the filepath value v contains a ".." entry. +// This will check filepath components by splitting along / or \. This +// function is copied directly from the Go net/http implementation. +func containsDotDot(v string) bool { + if !strings.Contains(v, "..") { + return false + } + for _, ent := range strings.FieldsFunc(v, isSlashRune) { + if ent == ".." { + return true + } + } + return false +} + +func isSlashRune(r rune) bool { return r == '/' || r == '\\' } diff --git a/vendor/github.com/hashicorp/go-getter/decompress_tar.go b/vendor/github.com/hashicorp/go-getter/decompress_tar.go index 543c30d21..39cb392e0 100644 --- a/vendor/github.com/hashicorp/go-getter/decompress_tar.go +++ b/vendor/github.com/hashicorp/go-getter/decompress_tar.go @@ -13,6 +13,7 @@ import ( func untar(input io.Reader, dst, src string, dir bool) error { tarR := tar.NewReader(input) done := false + dirHdrs := []*tar.Header{} for { hdr, err := tarR.Next() if err == io.EOF { @@ -21,7 +22,7 @@ func untar(input io.Reader, dst, src string, dir bool) error { return fmt.Errorf("empty archive: %s", src) } - return nil + break } if err != nil { return err @@ -34,6 +35,11 @@ func untar(input io.Reader, dst, src string, dir bool) error { path := dst if dir { + // Disallow parent traversal + if containsDotDot(hdr.Name) { + return fmt.Errorf("entry contains '..': %s", hdr.Name) + } + path = filepath.Join(path, hdr.Name) } @@ -47,6 +53,10 @@ func untar(input io.Reader, dst, src string, dir bool) error { return err } + // Record the directory information so that we may set its attributes + // after all files have been extracted + dirHdrs = append(dirHdrs, hdr) + continue } else { // There is no ordering guarantee that a file in a directory is @@ -84,7 +94,23 @@ func untar(input io.Reader, dst, src string, dir bool) error { if err := os.Chmod(path, hdr.FileInfo().Mode()); err != nil { return err } + + // Set the access and modification time + if err := os.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { + return err + } } + + // Adding a file or subdirectory changes the mtime of a directory + // We therefore wait until we've extracted everything and then set the mtime and atime attributes + for _, dirHdr := range dirHdrs { + path := filepath.Join(dst, dirHdr.Name) + if err := os.Chtimes(path, dirHdr.AccessTime, dirHdr.ModTime); err != nil { + return err + } + } + + return nil } // tarDecompressor is an implementation of Decompressor that can diff --git a/vendor/github.com/hashicorp/go-getter/decompress_testing.go b/vendor/github.com/hashicorp/go-getter/decompress_testing.go index 82b8ab4f6..91cf33d98 100644 --- a/vendor/github.com/hashicorp/go-getter/decompress_testing.go +++ b/vendor/github.com/hashicorp/go-getter/decompress_testing.go @@ -11,6 +11,7 @@ import ( "runtime" "sort" "strings" + "time" "github.com/mitchellh/go-testing-interface" ) @@ -22,6 +23,7 @@ type TestDecompressCase struct { Err bool // Err is whether we expect an error or not DirList []string // DirList is the list of files for Dir mode FileMD5 string // FileMD5 is the expected MD5 for a single file + Mtime *time.Time // Mtime is the optionally expected mtime for a single file (or all files if in Dir mode) } // TestDecompressor is a helper function for testing generic decompressors. @@ -68,6 +70,14 @@ func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) { } } + if tc.Mtime != nil { + actual := fi.ModTime() + expected := *tc.Mtime + if actual != expected { + t.Fatalf("err %s: expected mtime '%s' for %s, got '%s'", tc.Input, expected.String(), dst, actual.String()) + } + } + return } @@ -84,6 +94,21 @@ func TestDecompressor(t testing.T, d Decompressor, cases []TestDecompressCase) { if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected) } + // Check for correct atime/mtime + for _, dir := range actual { + path := filepath.Join(dst, dir) + if tc.Mtime != nil { + fi, err := os.Stat(path) + if err != nil { + t.Fatalf("err: %s", err) + } + actual := fi.ModTime() + expected := *tc.Mtime + if actual != expected { + t.Fatalf("err %s: expected mtime '%s' for %s, got '%s'", tc.Input, expected.String(), path, actual.String()) + } + } + } }() } } diff --git a/vendor/github.com/hashicorp/go-getter/decompress_zip.go b/vendor/github.com/hashicorp/go-getter/decompress_zip.go index a065c076f..b0e70cac3 100644 --- a/vendor/github.com/hashicorp/go-getter/decompress_zip.go +++ b/vendor/github.com/hashicorp/go-getter/decompress_zip.go @@ -42,6 +42,11 @@ func (d *ZipDecompressor) Decompress(dst, src string, dir bool) error { for _, f := range zipR.File { path := dst if dir { + // Disallow parent traversal + if containsDotDot(f.Name) { + return fmt.Errorf("entry contains '..': %s", f.Name) + } + path = filepath.Join(path, f.Name) } diff --git a/vendor/github.com/hashicorp/go-getter/get_git.go b/vendor/github.com/hashicorp/go-getter/get_git.go index 6f5d9142b..cb1d02947 100644 --- a/vendor/github.com/hashicorp/go-getter/get_git.go +++ b/vendor/github.com/hashicorp/go-getter/get_git.go @@ -11,6 +11,7 @@ import ( "strings" urlhelper "github.com/hashicorp/go-getter/helper/url" + "github.com/hashicorp/go-safetemp" "github.com/hashicorp/go-version" ) @@ -105,13 +106,11 @@ func (g *GitGetter) Get(dst string, u *url.URL) error { // GetFile for Git doesn't support updating at this time. It will download // the file every time. func (g *GitGetter) GetFile(dst string, u *url.URL) error { - td, err := ioutil.TempDir("", "getter-git") + td, tdcloser, err := safetemp.Dir("", "getter") if err != nil { return err } - if err := os.RemoveAll(td); err != nil { - return err - } + defer tdcloser.Close() // Get the filename, and strip the filename from the URL so we can // just get the repository directly. diff --git a/vendor/github.com/hashicorp/go-getter/get_hg.go b/vendor/github.com/hashicorp/go-getter/get_hg.go index 820bdd488..f38692270 100644 --- a/vendor/github.com/hashicorp/go-getter/get_hg.go +++ b/vendor/github.com/hashicorp/go-getter/get_hg.go @@ -2,7 +2,6 @@ package getter import ( "fmt" - "io/ioutil" "net/url" "os" "os/exec" @@ -10,6 +9,7 @@ import ( "runtime" urlhelper "github.com/hashicorp/go-getter/helper/url" + "github.com/hashicorp/go-safetemp" ) // HgGetter is a Getter implementation that will download a module from @@ -64,13 +64,13 @@ func (g *HgGetter) Get(dst string, u *url.URL) error { // GetFile for Hg doesn't support updating at this time. It will download // the file every time. func (g *HgGetter) GetFile(dst string, u *url.URL) error { - td, err := ioutil.TempDir("", "getter-hg") + // Create a temporary directory to store the full source. This has to be + // a non-existent directory. + td, tdcloser, err := safetemp.Dir("", "getter") if err != nil { return err } - if err := os.RemoveAll(td); err != nil { - return err - } + defer tdcloser.Close() // Get the filename, and strip the filename from the URL so we can // just get the repository directly. diff --git a/vendor/github.com/hashicorp/go-getter/get_http.go b/vendor/github.com/hashicorp/go-getter/get_http.go index 9acc72cd7..d2e28796d 100644 --- a/vendor/github.com/hashicorp/go-getter/get_http.go +++ b/vendor/github.com/hashicorp/go-getter/get_http.go @@ -4,12 +4,13 @@ import ( "encoding/xml" "fmt" "io" - "io/ioutil" "net/http" "net/url" "os" "path/filepath" "strings" + + "github.com/hashicorp/go-safetemp" ) // HttpGetter is a Getter implementation that will download from an HTTP @@ -135,25 +136,27 @@ func (g *HttpGetter) GetFile(dst string, u *url.URL) error { if err != nil { return err } - defer f.Close() - _, err = io.Copy(f, resp.Body) + n, err := io.Copy(f, resp.Body) + if err == nil && n < resp.ContentLength { + err = io.ErrShortWrite + } + if err1 := f.Close(); err == nil { + err = err1 + } return err } // getSubdir downloads the source into the destination, but with // the proper subdir. func (g *HttpGetter) getSubdir(dst, source, subDir string) error { - // Create a temporary directory to store the full source - td, err := ioutil.TempDir("", "tf") + // Create a temporary directory to store the full source. This has to be + // a non-existent directory. + td, tdcloser, err := safetemp.Dir("", "getter") if err != nil { return err } - defer os.RemoveAll(td) - - // We have to create a subdirectory that doesn't exist for the file - // getter to work. - td = filepath.Join(td, "data") + defer tdcloser.Close() // Download that into the given directory if err := Get(td, source); err != nil { diff --git a/vendor/github.com/hashicorp/go-safetemp/LICENSE b/vendor/github.com/hashicorp/go-safetemp/LICENSE new file mode 100644 index 000000000..be2cc4dfb --- /dev/null +++ b/vendor/github.com/hashicorp/go-safetemp/LICENSE @@ -0,0 +1,362 @@ +Mozilla Public License, version 2.0 + +1. Definitions + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to the + creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used by a + Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached the + notice in Exhibit A, the Executable Form of such Source Code Form, and + Modifications of such Source Code Form, in each case including portions + thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + a. that the initial Contributor has attached the notice described in + Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the terms of + a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in a + separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, whether + at the time of the initial grant or subsequently, any and all of the + rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered Software; or + + b. any new file in Source Code Form that contains any Covered Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the License, + by the making, using, selling, offering for sale, having made, import, + or transfer of either its Contributions or its Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU Lesser + General Public License, Version 2.1, the GNU Affero General Public + License, Version 3.0, or any later versions of those licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that controls, is + controlled by, or is under common control with You. For purposes of this + definition, "control" means (a) the power, direct or indirect, to cause + the direction or management of such entity, whether by contract or + otherwise, or (b) ownership of more than fifty percent (50%) of the + outstanding shares or beneficial ownership of such entity. + + +2. License Grants and Conditions + +2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, + non-exclusive license: + + a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + + b. under Patent Claims of such Contributor to make, use, sell, offer for + sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution + become effective for each Contribution on the date the Contributor first + distributes such Contribution. + +2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under + this License. No additional rights or licenses will be implied from the + distribution or licensing of Covered Software under this License. + Notwithstanding Section 2.1(b) above, no patent license is granted by a + Contributor: + + a. for any code that a Contributor has removed from Covered Software; or + + b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + + c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + + This License does not grant any rights in the trademarks, service marks, + or logos of any Contributor (except as may be necessary to comply with + the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to + distribute the Covered Software under a subsequent version of this + License (see Section 10.2) or under the terms of a Secondary License (if + permitted under the terms of Section 3.3). + +2.5. Representation + + Each Contributor represents that the Contributor believes its + Contributions are its original creation(s) or it has sufficient rights to + grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + + This License is not intended to limit any rights You have under + applicable copyright doctrines of fair use, fair dealing, or other + equivalents. + +2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in + Section 2.1. + + +3. Responsibilities + +3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any + Modifications that You create or to which You contribute, must be under + the terms of this License. You must inform recipients that the Source + Code Form of the Covered Software is governed by the terms of this + License, and how they can obtain a copy of this License. You may not + attempt to alter or restrict the recipients' rights in the Source Code + Form. + +3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + + a. such Covered Software must also be made available in Source Code Form, + as described in Section 3.1, and You must inform recipients of the + Executable Form how they can obtain a copy of such Source Code Form by + reasonable means in a timely manner, at a charge no more than the cost + of distribution to the recipient; and + + b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter the + recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, + provided that You also comply with the requirements of this License for + the Covered Software. If the Larger Work is a combination of Covered + Software with a work governed by one or more Secondary Licenses, and the + Covered Software is not Incompatible With Secondary Licenses, this + License permits You to additionally distribute such Covered Software + under the terms of such Secondary License(s), so that the recipient of + the Larger Work may, at their option, further distribute the Covered + Software under the terms of either this License or such Secondary + License(s). + +3.4. Notices + + You may not remove or alter the substance of any license notices + (including copyright notices, patent notices, disclaimers of warranty, or + limitations of liability) contained within the Source Code Form of the + Covered Software, except that You may alter any license notices to the + extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered + Software. However, You may do so only on Your own behalf, and not on + behalf of any Contributor. You must make it absolutely clear that any + such warranty, support, indemnity, or liability obligation is offered by + You alone, and You hereby agree to indemnify every Contributor for any + liability incurred by such Contributor as a result of warranty, support, + indemnity or liability terms You offer. You may include additional + disclaimers of warranty and limitations of liability specific to any + jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + + If it is impossible for You to comply with any of the terms of this License + with respect to some or all of the Covered Software due to statute, + judicial order, or regulation then You must: (a) comply with the terms of + this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be placed in a + text file included with all distributions of the Covered Software under + this License. Except to the extent prohibited by statute or regulation, + such description must be sufficiently detailed for a recipient of ordinary + skill to be able to understand it. + +5. Termination + +5.1. The rights granted under this License will terminate automatically if You + fail to comply with any of its terms. However, if You become compliant, + then the rights granted under this License from a particular Contributor + are reinstated (a) provisionally, unless and until such Contributor + explicitly and finally terminates Your grants, and (b) on an ongoing + basis, if such Contributor fails to notify You of the non-compliance by + some reasonable means prior to 60 days after You have come back into + compliance. Moreover, Your grants from a particular Contributor are + reinstated on an ongoing basis if such Contributor notifies You of the + non-compliance by some reasonable means, this is the first time You have + received notice of non-compliance with this License from such + Contributor, and You become compliant prior to 30 days after Your receipt + of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent + infringement claim (excluding declaratory judgment actions, + counter-claims, and cross-claims) alleging that a Contributor Version + directly or indirectly infringes any patent, then the rights granted to + You by any and all Contributors for the Covered Software under Section + 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user + license agreements (excluding distributors and resellers) which have been + validly granted by You or Your distributors under this License prior to + termination shall survive termination. + +6. Disclaimer of Warranty + + Covered Software is provided under this License on an "as is" basis, + without warranty of any kind, either expressed, implied, or statutory, + including, without limitation, warranties that the Covered Software is free + of defects, merchantable, fit for a particular purpose or non-infringing. + The entire risk as to the quality and performance of the Covered Software + is with You. Should any Covered Software prove defective in any respect, + You (not any Contributor) assume the cost of any necessary servicing, + repair, or correction. This disclaimer of warranty constitutes an essential + part of this License. No use of any Covered Software is authorized under + this License except under this disclaimer. + +7. Limitation of Liability + + Under no circumstances and under no legal theory, whether tort (including + negligence), contract, or otherwise, shall any Contributor, or anyone who + distributes Covered Software as permitted above, be liable to You for any + direct, indirect, special, incidental, or consequential damages of any + character including, without limitation, damages for lost profits, loss of + goodwill, work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses, even if such party shall have been + informed of the possibility of such damages. This limitation of liability + shall not apply to liability for death or personal injury resulting from + such party's negligence to the extent applicable law prohibits such + limitation. Some jurisdictions do not allow the exclusion or limitation of + incidental or consequential damages, so this exclusion and limitation may + not apply to You. + +8. Litigation + + Any litigation relating to this License may be brought only in the courts + of a jurisdiction where the defendant maintains its principal place of + business and such litigation shall be governed by laws of that + jurisdiction, without reference to its conflict-of-law provisions. Nothing + in this Section shall prevent a party's ability to bring cross-claims or + counter-claims. + +9. Miscellaneous + + This License represents the complete agreement concerning the subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. Any law or regulation which provides that + the language of a contract shall be construed against the drafter shall not + be used to construe this License against a Contributor. + + +10. Versions of the License + +10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section + 10.3, no one other than the license steward has the right to modify or + publish new versions of this License. Each version will be given a + distinguishing version number. + +10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version + of the License under which You originally received the Covered Software, + or under the terms of any subsequent version published by the license + steward. + +10.3. Modified Versions + + If you create software not governed by this License, and you want to + create a new license for such software, you may create and use a + modified version of this License if you rename the license and remove + any references to the name of the license steward (except to note that + such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary + Licenses If You choose to distribute Source Code Form that is + Incompatible With Secondary Licenses under the terms of this version of + the License, the notice described in Exhibit B of this License must be + attached. + +Exhibit A - Source Code Form License Notice + + This Source Code Form is subject to the + terms of the Mozilla Public License, v. + 2.0. If a copy of the MPL was not + distributed with this file, You can + obtain one at + http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, +then You may include the notice in a location (such as a LICENSE file in a +relevant directory) where a recipient would be likely to look for such a +notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + + This Source Code Form is "Incompatible + With Secondary Licenses", as defined by + the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/hashicorp/go-safetemp/README.md b/vendor/github.com/hashicorp/go-safetemp/README.md new file mode 100644 index 000000000..02ece3317 --- /dev/null +++ b/vendor/github.com/hashicorp/go-safetemp/README.md @@ -0,0 +1,10 @@ +# go-safetemp +[![Godoc](https://godoc.org/github.com/hashcorp/go-safetemp?status.svg)](https://godoc.org/github.com/hashicorp/go-safetemp) + +Functions for safely working with temporary directories and files. + +## Why? + +The Go standard library provides the excellent `ioutil` package for +working with temporary directories and files. This library builds on top +of that to provide safe abstractions above that. diff --git a/vendor/github.com/hashicorp/go-safetemp/safetemp.go b/vendor/github.com/hashicorp/go-safetemp/safetemp.go new file mode 100644 index 000000000..c4ae72b78 --- /dev/null +++ b/vendor/github.com/hashicorp/go-safetemp/safetemp.go @@ -0,0 +1,40 @@ +package safetemp + +import ( + "io" + "io/ioutil" + "os" + "path/filepath" +) + +// Dir creates a new temporary directory that isn't yet created. This +// can be used with calls that expect a non-existent directory. +// +// The directory is created as a child of a temporary directory created +// within the directory dir starting with prefix. The temporary directory +// returned is always named "temp". The parent directory has the specified +// prefix. +// +// The returned io.Closer should be used to clean up the returned directory. +// This will properly remove the returned directory and any other temporary +// files created. +// +// If an error is returned, the Closer does not need to be called (and will +// be nil). +func Dir(dir, prefix string) (string, io.Closer, error) { + // Create the temporary directory + td, err := ioutil.TempDir(dir, prefix) + if err != nil { + return "", nil, err + } + + return filepath.Join(td, "temp"), pathCloser(td), nil +} + +// pathCloser implements io.Closer to remove the given path on Close. +type pathCloser string + +// Close deletes this path. +func (p pathCloser) Close() error { + return os.RemoveAll(string(p)) +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 1298f887d..6dcdd3558 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1591,10 +1591,10 @@ "versionExact": "master" }, { - "checksumSHA1": "9VcI9QGCShWIUIL187qRd4sxwb8=", + "checksumSHA1": "fvjFEz5PBN1m9ALWf9UuLgTFWLg=", "path": "github.com/hashicorp/go-getter", - "revision": "a686900cb3753aa644dc4812be91ceaf9fdd3b98", - "revisionTime": "2017-09-22T19:29:48Z", + "revision": "90bb99a48d86cf1d327cee9968f7428f90ba13c1", + "revisionTime": "2018-03-27T01:01:14Z", "version": "master", "versionExact": "master" }, @@ -1637,6 +1637,12 @@ "revision": "6bb64b370b90e7ef1fa532be9e591a81c3493e00", "revisionTime": "2016-05-03T14:34:40Z" }, + { + "checksumSHA1": "CduvzBFfTv77nhjtXPGdIjQQLMI=", + "path": "github.com/hashicorp/go-safetemp", + "revision": "b1a1dbde6fdc11e3ae79efd9039009e22d4ae240", + "revisionTime": "2018-03-26T21:11:50Z" + }, { "checksumSHA1": "85XUnluYJL7F55ptcwdmN8eSOsk=", "path": "github.com/hashicorp/go-uuid", From 227285d7d097c46331ed0c8926f078b49b8874b3 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 10 Apr 2018 12:13:00 -0400 Subject: [PATCH 14/15] update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e521f2964..c75534e1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.11.7 (Unreleased) +BUG FIXES: + +* core: Fix handling of interpolated counts when applying a destroy plan [GH-17824] + PROVIDER SDK CHANGES (not user-facing): * helper/schema: Invoking `ForceNew` on a key being removed from config during From 41e50bd32a8825a84535e353c3674af8ce799161 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 10 Apr 2018 16:50:42 +0000 Subject: [PATCH 15/15] v0.11.7 --- CHANGELOG.md | 8 ++++---- version/version.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c75534e1c..1013f8c6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,19 @@ -## 0.11.7 (Unreleased) +## 0.11.7 (April 10, 2018) BUG FIXES: -* core: Fix handling of interpolated counts when applying a destroy plan [GH-17824] +* core: Fix handling of interpolated counts when applying a destroy plan ([#17824](https://github.com/hashicorp/terraform/issues/17824)) PROVIDER SDK CHANGES (not user-facing): * helper/schema: Invoking `ForceNew` on a key being removed from config during diff customization now correctly exposes that key as being removed in the updated diff. This prevents diff mismatches under certain circumstances. - [GH-17811] + ([#17811](https://github.com/hashicorp/terraform/issues/17811)) * helper/schema: Invoking `ForceNew` during diff customization on its own no longer writes any new data to the diff. This prevents writing of new nil to zero value diffs for sub-fields of complex lists and sets where a diff did not - exist before. [GH-17811] + exist before. ([#17811](https://github.com/hashicorp/terraform/issues/17811)) ## 0.11.6 (April 5, 2018) diff --git a/version/version.go b/version/version.go index 6693b0e1c..3b982dbdb 100644 --- a/version/version.go +++ b/version/version.go @@ -16,7 +16,7 @@ const Version = "0.11.7" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. -var Prerelease = "dev" +var Prerelease = "" // SemVer is an instance of version.Version. This has the secondary // benefit of verifying during tests and init time that our version is a