Hello community, here is the log from the commit of package terraform for openSUSE:Factory checked in at 2019-11-21 13:00:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/terraform (Old) and /work/SRC/openSUSE:Factory/.terraform.new.26869 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "terraform" Thu Nov 21 13:00:00 2019 rev:14 rq:750056 version:0.12.16 Changes: -------- --- /work/SRC/openSUSE:Factory/terraform/terraform.changes 2019-11-15 22:39:26.612357169 +0100 +++ /work/SRC/openSUSE:Factory/.terraform.new.26869/terraform.changes 2019-11-21 13:00:11.718499629 +0100 @@ -1,0 +2,10 @@ +Wed Nov 20 12:02:18 UTC 2019 - Petr Cervinka <[email protected]> + +- Increase required go version to 1.12 +- Update to 0.12.16 + BUG FIXES: + * command/0.12upgrade: fix panic when int value is out of range ([#23394](https://github.com/hashicorp/terraform/issues/23394)) + * core: fix cycle between dependencies with create_before_destroy ([#23399](https://github.com/hashicorp/terraform/issues/23399)) + * backend/remote: default .terraformignore paths will now work on Windows ([#23311](https://github.com/hashicorp/terraform/issues/23311)) + +------------------------------------------------------------------- Old: ---- terraform-0.12.15.obscpio terraform-0.12.15.tar.xz New: ---- terraform-0.12.16.obscpio terraform-0.12.16.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ terraform.spec ++++++ --- /var/tmp/diff_new_pack.SHsbNT/_old 2019-11-21 13:00:13.710499016 +0100 +++ /var/tmp/diff_new_pack.SHsbNT/_new 2019-11-21 13:00:13.710499016 +0100 @@ -17,7 +17,7 @@ Name: terraform -Version: 0.12.15 +Version: 0.12.16 Release: 0 Summary: Tool for building infrastructure safely and efficiently License: MPL-2.0 @@ -25,7 +25,7 @@ URL: https://www.terraform.io/ Source: %{name}-%{version}.tar.xz Source99: terraform-rpmlintrc -BuildRequires: golang(API) >= 1.11 +BuildRequires: golang(API) >= 1.12 BuildRequires: golang-packaging BuildRequires: xz # See: https://github.com/hashicorp/terraform/issues/22807 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.SHsbNT/_old 2019-11-21 13:00:13.770498997 +0100 +++ /var/tmp/diff_new_pack.SHsbNT/_new 2019-11-21 13:00:13.770498997 +0100 @@ -3,8 +3,8 @@ <param name="url">https://github.com/hashicorp/terraform.git</param> <param name="scm">git</param> <param name="filename">terraform</param> - <param name="versionformat">0.12.15</param> - <param name="revision">v0.12.15</param> + <param name="versionformat">0.12.16</param> + <param name="revision">v0.12.16</param> <param name="exclude">.git</param> </service> <service name="tar" mode="disabled"/> ++++++ terraform-0.12.15.obscpio -> terraform-0.12.16.obscpio ++++++ /work/SRC/openSUSE:Factory/terraform/terraform-0.12.15.obscpio /work/SRC/openSUSE:Factory/.terraform.new.26869/terraform-0.12.16.obscpio differ: char 49, line 1 ++++++ terraform-0.12.15.tar.xz -> terraform-0.12.16.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/CHANGELOG.md new/terraform-0.12.16/CHANGELOG.md --- old/terraform-0.12.15/CHANGELOG.md 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/CHANGELOG.md 2019-11-18 23:09:27.000000000 +0100 @@ -1,3 +1,15 @@ +## 0.12.16 (November 18, 2019) + +NEW FEATURES: + +* lang/funcs: Add `trim*` functions + +BUG FIXES: + +* command/0.12upgrade: fix panic when int value is out of range ([#23394](https://github.com/hashicorp/terraform/issues/23394)) +* core: fix cycle between dependencies with create_before_destroy ([#23399](https://github.com/hashicorp/terraform/issues/23399)) +* backend/remote: default .terraformignore paths will now work on Windows ([#23311](https://github.com/hashicorp/terraform/issues/23311)) + ## 0.12.15 (November 14, 2019) BUG FIXES: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/command/format/diff.go new/terraform-0.12.16/command/format/diff.go --- old/terraform-0.12.15/command/format/diff.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/command/format/diff.go 2019-11-18 23:09:27.000000000 +0100 @@ -502,7 +502,7 @@ ty, err := ctyjson.ImpliedType(src) // check for the special case of "null", which decodes to nil, // and just allow it to be printed out directly - if err == nil && !ty.IsPrimitiveType() && val.AsString() != "null" { + if err == nil && !ty.IsPrimitiveType() && strings.TrimSpace(val.AsString()) != "null" { jv, err := ctyjson.Unmarshal(src, ty) if err == nil { p.buf.WriteString("jsonencode(") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/command/format/diff_test.go new/terraform-0.12.16/command/format/diff_test.go --- old/terraform-0.12.15/command/format/diff_test.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/command/format/diff_test.go 2019-11-18 23:09:27.000000000 +0100 @@ -52,6 +52,26 @@ } `, }, + "creation (null string with extra whitespace)": { + Action: plans.Create, + Mode: addrs.ManagedResourceMode, + Before: cty.NullVal(cty.EmptyObject), + After: cty.ObjectVal(map[string]cty.Value{ + "string": cty.StringVal("null "), + }), + Schema: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "string": {Type: cty.String, Optional: true}, + }, + }, + RequiredReplace: cty.NewPathSet(), + Tainted: false, + ExpectedOutput: ` # test_instance.example will be created + + resource "test_instance" "example" { + + string = "null " + } +`, + }, "deletion": { Action: plans.Delete, Mode: addrs.ManagedResourceMode, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/configs/configupgrade/upgrade_expr.go new/terraform-0.12.16/configs/configupgrade/upgrade_expr.go --- old/terraform-0.12.15/configs/configupgrade/upgrade_expr.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/configs/configupgrade/upgrade_expr.go 2019-11-18 23:09:27.000000000 +0100 @@ -38,9 +38,9 @@ return upgradeExpr(tv.Token, filename, interp, an) case hcl1token.Token: - litVal := tv.Value() switch tv.Type { case hcl1token.STRING: + litVal := tv.Value() if !interp { // Easy case, then. printQuotedString(&buf, litVal.(string)) @@ -141,6 +141,7 @@ buf.WriteString(marker) case hcl1token.BOOL: + litVal := tv.Value() if litVal.(bool) { buf.WriteString("true") } else { @@ -148,12 +149,28 @@ } case hcl1token.NUMBER: - num := tv.Value() - buf.WriteString(strconv.FormatInt(num.(int64), 10)) + num, err := strconv.ParseInt(tv.Text, 0, 64) + if err != nil { + diags = diags.Append(&hcl2.Diagnostic{ + Severity: hcl2.DiagError, + Summary: "Invalid number value", + Detail: fmt.Sprintf("Parsing failed: %s", err), + Subject: hcl1PosRange(filename, tv.Pos).Ptr(), + }) + } + buf.WriteString(strconv.FormatInt(num, 10)) case hcl1token.FLOAT: - num := tv.Value() - buf.WriteString(strconv.FormatFloat(num.(float64), 'f', -1, 64)) + num, err := strconv.ParseFloat(tv.Text, 64) + if err != nil { + diags = diags.Append(&hcl2.Diagnostic{ + Severity: hcl2.DiagError, + Summary: "Invalid float value", + Detail: fmt.Sprintf("Parsing failed: %s", err), + Subject: hcl1PosRange(filename, tv.Pos).Ptr(), + }) + } + buf.WriteString(strconv.FormatFloat(num, 'f', -1, 64)) default: // For everything else we'll just pass through the given bytes verbatim, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/go.mod new/terraform-0.12.16/go.mod --- old/terraform-0.12.15/go.mod 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/go.mod 2019-11-18 23:09:27.000000000 +0100 @@ -64,7 +64,7 @@ github.com/hashicorp/go-retryablehttp v0.5.2 github.com/hashicorp/go-rootcerts v1.0.0 github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 // indirect - github.com/hashicorp/go-tfe v0.3.25 + github.com/hashicorp/go-tfe v0.3.27 github.com/hashicorp/go-uuid v1.0.1 github.com/hashicorp/go-version v1.2.0 github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/go.sum new/terraform-0.12.16/go.sum --- old/terraform-0.12.15/go.sum 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/go.sum 2019-11-18 23:09:27.000000000 +0100 @@ -197,12 +197,12 @@ github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= -github.com/hashicorp/go-slug v0.4.0 h1:YSz3afoEZZJVVB46NITf0+opd2cHpaYJ1XSojOyP0x8= -github.com/hashicorp/go-slug v0.4.0/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8= +github.com/hashicorp/go-slug v0.4.1 h1:/jAo8dNuLgSImoLXaX7Od7QB4TfYCVPam+OpAt5bZqc= +github.com/hashicorp/go-slug v0.4.1/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8= github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 h1:7YOlAIO2YWnJZkQp7B5eFykaIY7C9JndqAFQyVV5BhM= github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-tfe v0.3.25 h1:4rPk/9rSYuRoujKk5FsxSvtC/AjJCQphLS/57yr6wUM= -github.com/hashicorp/go-tfe v0.3.25/go.mod h1:IJQ30WzRajD/W0Z8SY4lhuoOX8h5saTe95t80z8hRsk= +github.com/hashicorp/go-tfe v0.3.27 h1:7XZ/ZoPyYoeuNXaWWW0mJOq016y0qb7I4Q0P/cagyu8= +github.com/hashicorp/go-tfe v0.3.27/go.mod h1:DVPSW2ogH+M9W1/i50ASgMht8cHP7NxxK0nrY9aFikQ= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/lang/funcs/string.go new/terraform-0.12.16/lang/funcs/string.go --- old/terraform-0.12.15/lang/funcs/string.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/lang/funcs/string.go 2019-11-18 23:09:27.000000000 +0100 @@ -123,7 +123,7 @@ }, }) -// ChompFunc constructions a function that removes newline characters at the end of a string. +// ChompFunc constructs a function that removes newline characters at the end of a string. var ChompFunc = function.New(&function.Spec{ Params: []function.Parameter{ { @@ -138,7 +138,7 @@ }, }) -// IndentFunc constructions a function that adds a given number of spaces to the +// IndentFunc constructs a function that adds a given number of spaces to the // beginnings of all but the first line in a given multi-line string. var IndentFunc = function.New(&function.Spec{ Params: []function.Parameter{ @@ -163,7 +163,7 @@ }, }) -// ReplaceFunc constructions a function that searches a given string for another +// ReplaceFunc constructs a function that searches a given string for another // given substring, and replaces each occurence with a given replacement string. var ReplaceFunc = function.New(&function.Spec{ Params: []function.Parameter{ @@ -201,7 +201,7 @@ }, }) -// TitleFunc constructions a function that converts the first letter of each word +// TitleFunc constructs a function that converts the first letter of each word // in the given string to uppercase. var TitleFunc = function.New(&function.Spec{ Params: []function.Parameter{ @@ -216,7 +216,7 @@ }, }) -// TrimSpaceFunc constructions a function that removes any space characters from +// TrimSpaceFunc constructs a function that removes any space characters from // the start and end of the given string. var TrimSpaceFunc = function.New(&function.Spec{ Params: []function.Parameter{ @@ -231,6 +231,69 @@ }, }) +// TrimFunc constructs a function that removes the specified characters from +// the start and end of the given string. +var TrimFunc = function.New(&function.Spec{ + Params: []function.Parameter{ + { + Name: "str", + Type: cty.String, + }, + { + Name: "cutset", + Type: cty.String, + }, + }, + Type: function.StaticReturnType(cty.String), + Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { + str := args[0].AsString() + cutset := args[1].AsString() + return cty.StringVal(strings.Trim(str, cutset)), nil + }, +}) + +// TrimPrefixFunc constructs a function that removes the specified characters from +// the start the given string. +var TrimPrefixFunc = function.New(&function.Spec{ + Params: []function.Parameter{ + { + Name: "str", + Type: cty.String, + }, + { + Name: "prefix", + Type: cty.String, + }, + }, + Type: function.StaticReturnType(cty.String), + Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { + str := args[0].AsString() + prefix := args[1].AsString() + return cty.StringVal(strings.TrimPrefix(str, prefix)), nil + }, +}) + +// TrimSuffixFunc constructs a function that removes the specified characters from +// the end of the given string. +var TrimSuffixFunc = function.New(&function.Spec{ + Params: []function.Parameter{ + { + Name: "str", + Type: cty.String, + }, + { + Name: "suffix", + Type: cty.String, + }, + }, + Type: function.StaticReturnType(cty.String), + Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { + str := args[0].AsString() + cutset := args[1].AsString() + return cty.StringVal(strings.TrimSuffix(str, cutset)), nil + }, +}) + // Join concatenates together the string elements of one or more lists with a // given separator. func Join(sep cty.Value, lists ...cty.Value) (cty.Value, error) { @@ -278,3 +341,18 @@ func TrimSpace(str cty.Value) (cty.Value, error) { return TrimSpaceFunc.Call([]cty.Value{str}) } + +// Trim removes the specified characters from the start and end of the given string. +func Trim(str, cutset cty.Value) (cty.Value, error) { + return TrimFunc.Call([]cty.Value{str, cutset}) +} + +// TrimPrefix removes the specified prefix from the start of the given string. +func TrimPrefix(str, prefix cty.Value) (cty.Value, error) { + return TrimPrefixFunc.Call([]cty.Value{str, prefix}) +} + +// TrimSuffix removes the specified suffix from the end of the given string. +func TrimSuffix(str, suffix cty.Value) (cty.Value, error) { + return TrimSuffixFunc.Call([]cty.Value{str, suffix}) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/lang/funcs/string_test.go new/terraform-0.12.16/lang/funcs/string_test.go --- old/terraform-0.12.15/lang/funcs/string_test.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/lang/funcs/string_test.go 2019-11-18 23:09:27.000000000 +0100 @@ -506,3 +506,126 @@ }) } } + +func TestTrim(t *testing.T) { + tests := []struct { + String cty.Value + Cutset cty.Value + Want cty.Value + Err bool + }{ + { + cty.StringVal("!? test ?!"), + cty.StringVal("?!"), + cty.StringVal(" test "), + false, + }, + { + cty.StringVal("...test..."), + cty.StringVal("."), + cty.StringVal("test"), + false, + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("trim(%#v, %#v)", test.String, test.Cutset), func(t *testing.T) { + got, err := Trim(test.String, test.Cutset) + + if test.Err { + if err == nil { + t.Fatal("succeeded; want error") + } + return + } else if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + if !got.RawEquals(test.Want) { + t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) + } + }) + } +} + +func TestTrimPrefix(t *testing.T) { + tests := []struct { + String cty.Value + Prefix cty.Value + Want cty.Value + Err bool + }{ + { + cty.StringVal("helloworld"), + cty.StringVal("hello"), + cty.StringVal("world"), + false, + }, + { + cty.StringVal("...test..."), + cty.StringVal("."), + cty.StringVal("..test..."), + false, + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("trimprefix(%#v, %#v)", test.String, test.Prefix), func(t *testing.T) { + got, err := TrimPrefix(test.String, test.Prefix) + + if test.Err { + if err == nil { + t.Fatal("succeeded; want error") + } + return + } else if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + if !got.RawEquals(test.Want) { + t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) + } + }) + } +} + +func TestTrimSuffix(t *testing.T) { + tests := []struct { + String cty.Value + Suffix cty.Value + Want cty.Value + Err bool + }{ + { + cty.StringVal("helloworld"), + cty.StringVal("world"), + cty.StringVal("hello"), + false, + }, + { + cty.StringVal("...test..."), + cty.StringVal("."), + cty.StringVal("...test.."), + false, + }, + } + + for _, test := range tests { + t.Run(fmt.Sprintf("trimright(%#v, %#v)", test.String, test.Suffix), func(t *testing.T) { + got, err := TrimSuffix(test.String, test.Suffix) + + if test.Err { + if err == nil { + t.Fatal("succeeded; want error") + } + return + } else if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + if !got.RawEquals(test.Want) { + t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) + } + }) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/terraform/context_apply_test.go new/terraform-0.12.16/terraform/context_apply_test.go --- old/terraform-0.12.15/terraform/context_apply_test.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/terraform/context_apply_test.go 2019-11-18 23:09:27.000000000 +0100 @@ -11099,3 +11099,121 @@ t.Fatalf("unexpected attrs for c: %q\n", c.Current.AttrsJSON) } } + +func TestContext2Apply_cbdCycle(t *testing.T) { + m, snap := testModuleWithSnapshot(t, "apply-cbd-cycle") + p := testProvider("test") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + + state := states.NewState() + root := state.EnsureModule(addrs.RootModuleInstance) + root.SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_instance", + Name: "a", + }.Instance(addrs.NoKey), + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + AttrsJSON: []byte(`{"id":"a","require_new":"old","foo":"b"}`), + Dependencies: []addrs.AbsResource{ + addrs.AbsResource{ + Resource: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_instance", + Name: "b", + }, + Module: addrs.RootModuleInstance, + }, + addrs.AbsResource{ + Resource: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_instance", + Name: "c", + }, + Module: addrs.RootModuleInstance, + }, + }, + }, + addrs.ProviderConfig{ + Type: "test", + }.Absolute(addrs.RootModuleInstance), + ) + root.SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_instance", + Name: "b", + }.Instance(addrs.NoKey), + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + AttrsJSON: []byte(`{"id":"b","require_new":"old","foo":"c"}`), + Dependencies: []addrs.AbsResource{ + addrs.AbsResource{ + Resource: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_instance", + Name: "c", + }, + Module: addrs.RootModuleInstance, + }, + }, + }, + addrs.ProviderConfig{ + Type: "test", + }.Absolute(addrs.RootModuleInstance), + ) + root.SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_instance", + Name: "c", + }.Instance(addrs.NoKey), + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + AttrsJSON: []byte(`{"id":"c","require_new":"old"}`), + }, + addrs.ProviderConfig{ + Type: "test", + }.Absolute(addrs.RootModuleInstance), + ) + + providerResolver := providers.ResolverFixed( + map[string]providers.Factory{ + "test": testProviderFuncFixed(p), + }, + ) + + hook := &testHook{} + ctx := testContext2(t, &ContextOpts{ + Config: m, + ProviderResolver: providerResolver, + State: state, + Hooks: []Hook{hook}, + }) + + plan, diags := ctx.Plan() + diags.HasErrors() + if diags.HasErrors() { + t.Fatalf("diags: %s", diags.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 + ctxOpts, err := contextOptsForPlanViaFile(snap, state, plan) + if err != nil { + t.Fatal(err) + } + ctxOpts.ProviderResolver = providerResolver + ctx, diags = NewContext(ctxOpts) + if diags.HasErrors() { + t.Fatalf("failed to create context for plan: %s", diags.Err()) + } + + _, diags = ctx.Apply() + if diags.HasErrors() { + t.Fatalf("diags: %s", diags.Err()) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/terraform/context_refresh_test.go new/terraform-0.12.16/terraform/context_refresh_test.go --- old/terraform-0.12.15/terraform/context_refresh_test.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/terraform/context_refresh_test.go 2019-11-18 23:09:27.000000000 +0100 @@ -1978,6 +1978,17 @@ &states.ResourceInstanceObjectSrc{ Status: states.ObjectReady, AttrsJSON: []byte(`{"id":"foo"}`), + Dependencies: []addrs.AbsResource{ + // Existing dependencies should not be removed during refresh + { + Module: addrs.RootModuleInstance, + Resource: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "aws_instance", + Name: "baz", + }, + }, + }, }, addrs.ProviderConfig{ Type: "aws", @@ -1992,17 +2003,6 @@ &states.ResourceInstanceObjectSrc{ Status: states.ObjectReady, AttrsJSON: []byte(`{"id":"bar","foo":"foo"}`), - Dependencies: []addrs.AbsResource{ - // Existing dependencies should not be removed during refresh - { - Module: addrs.RootModuleInstance, - Resource: addrs.Resource{ - Mode: addrs.ManagedResourceMode, - Type: "aws_instance", - Name: "baz", - }, - }, - }, }, addrs.ProviderConfig{ Type: "aws", @@ -2045,11 +2045,13 @@ foo = foo Dependencies: - aws_instance.baz aws_instance.foo aws_instance.foo: ID = foo provider = provider.aws + + Dependencies: + aws_instance.baz `) checkStateString(t, result, expect) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/terraform/eval_state.go new/terraform-0.12.16/terraform/eval_state.go --- old/terraform-0.12.15/terraform/eval_state.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/terraform/eval_state.go 2019-11-18 23:09:27.000000000 +0100 @@ -508,8 +508,13 @@ depMap[d.String()] = d } - for _, d := range state.Dependencies { - depMap[d.String()] = d + // We have already dependencies in state, so we need to trust those for + // refresh. We can't write out new dependencies until apply time in case + // the configuration has been changed in a manner the conflicts with the + // stored dependencies. + if len(state.Dependencies) > 0 { + *n.Dependencies = state.Dependencies + return nil, nil } deps := make([]addrs.AbsResource, 0, len(depMap)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/terraform/testdata/apply-cbd-cycle/main.tf new/terraform-0.12.16/terraform/testdata/apply-cbd-cycle/main.tf --- old/terraform-0.12.15/terraform/testdata/apply-cbd-cycle/main.tf 1970-01-01 01:00:00.000000000 +0100 +++ new/terraform-0.12.16/terraform/testdata/apply-cbd-cycle/main.tf 2019-11-18 23:09:27.000000000 +0100 @@ -0,0 +1,19 @@ +resource "test_instance" "a" { + foo = test_instance.b.id + require_new = "changed" + + lifecycle { + create_before_destroy = true + } +} + +resource "test_instance" "b" { + foo = test_instance.c.id + require_new = "changed" +} + + +resource "test_instance" "c" { + require_new = "changed" +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/terraform/transform_destroy_cbd.go new/terraform-0.12.16/terraform/transform_destroy_cbd.go --- old/terraform-0.12.15/terraform/transform_destroy_cbd.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/terraform/transform_destroy_cbd.go 2019-11-18 23:09:27.000000000 +0100 @@ -160,23 +160,27 @@ continue } - // Find the destroy edge. There should only be one. + // Find the resource edges for _, e := range g.EdgesTo(v) { - // Not a destroy edge, ignore it - de, ok := e.(*DestroyEdge) - if !ok { - continue + switch de := e.(type) { + case *DestroyEdge: + // we need to invert the destroy edge from the create node + log.Printf("[TRACE] CBDEdgeTransformer: inverting edge: %s => %s", + dag.VertexName(de.Source()), dag.VertexName(de.Target())) + + // Found it! Invert. + g.RemoveEdge(de) + applyNode := de.Source() + destroyNode := de.Target() + g.Connect(&DestroyEdge{S: destroyNode, T: applyNode}) + default: + // We cannot have any direct dependencies from creators when + // the node is CBD without inducing a cycle. + if _, ok := e.Source().(GraphNodeCreator); ok { + log.Printf("[TRACE] CBDEdgeTransformer: removing non DestroyEdge to CBD destroy node: %s => %s", dag.VertexName(e.Source()), dag.VertexName(e.Target())) + g.RemoveEdge(e) + } } - - log.Printf("[TRACE] CBDEdgeTransformer: inverting edge: %s => %s", - dag.VertexName(de.Source()), dag.VertexName(de.Target())) - - // Found it! Invert. - g.RemoveEdge(de) - applyNode := de.Source() - destroyNode := de.Target() - g.Connect(&DestroyEdge{S: destroyNode, T: applyNode}) - break } // If the address has an index, we strip that. Our depMap creation @@ -289,7 +293,11 @@ // Keep track of the destroy nodes that this address // needs to depend on. key := rn.ResourceAddr().String() - depMap[key] = append(depMap[key], dns...) + + // we only need to record the same dns once + if _, ok := depMap[key]; !ok { + depMap[key] = append(depMap[key], dns...) + } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/terraform/transform_destroy_edge.go new/terraform-0.12.16/terraform/transform_destroy_edge.go --- old/terraform-0.12.15/terraform/transform_destroy_edge.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/terraform/transform_destroy_edge.go 2019-11-18 23:09:27.000000000 +0100 @@ -122,6 +122,12 @@ for _, resAddr := range ri.StateDependencies() { for _, desDep := range destroyersByResource[resAddr.String()] { + // TODO: don't connect this if c is CreateBeforeDestroy. + // This will require getting the actual change action at + // this point, since the lifecycle may have been forced + // by a dependent. This should prevent needing to prune + // the edge back out in CBDEdgeTransformer, and allow + // non-CBD nodes to depend on CBD destroys directly. log.Printf("[TRACE] DestroyEdgeTransformer: %s has stored dependency of %s\n", dag.VertexName(c), dag.VertexName(desDep)) g.Connect(dag.BasicEdge(c, desDep)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/vendor/github.com/hashicorp/go-slug/terraformignore.go new/terraform-0.12.16/vendor/github.com/hashicorp/go-slug/terraformignore.go --- old/terraform-0.12.15/vendor/github.com/hashicorp/go-slug/terraformignore.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/vendor/github.com/hashicorp/go-slug/terraformignore.go 2019-11-18 23:09:27.000000000 +0100 @@ -196,15 +196,15 @@ var defaultExclusions = []rule{ { - val: "**/.git/**", + val: strings.Join([]string{"**", ".git", "**"}, string(os.PathSeparator)), excluded: false, }, { - val: "**/.terraform/**", + val: strings.Join([]string{"**", ".terraform", "**"}, string(os.PathSeparator)), excluded: false, }, { - val: "**/.terraform/modules/**", + val: strings.Join([]string{"**", ".terraform", "modules", "**"}, string(os.PathSeparator)), excluded: true, }, } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/vendor/github.com/hashicorp/go-tfe/README.md new/terraform-0.12.16/vendor/github.com/hashicorp/go-tfe/README.md --- old/terraform-0.12.15/vendor/github.com/hashicorp/go-tfe/README.md 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/vendor/github.com/hashicorp/go-tfe/README.md 2019-11-18 23:09:27.000000000 +0100 @@ -128,28 +128,109 @@ ## Running tests +### 1. (Optional) Create a policy sets repo + +If you are planning to run the full suite of tests or work on policy sets, you'll need to set up a policy set repository in GitHub. + +Your policy set repository will need the following: +1. A policy set stored in a subdirectory `policy-sets/foo` +1. A branch other than master named `policies` + +### 2. Set up environment variables + +##### Required: Tests are run against an actual backend so they require a valid backend address -and token. In addition it also needs a Github token for running the OAuth Client -tests: +and token. +1. `TFE_ADDRESS` - URL of a Terraform Cloud or Terraform Enterprise instance to be used for testing, including scheme. Example: `https://tfe.local` +1. `TFE_TOKEN` - A [user API token](https://www.terraform.io/docs/cloud/users-teams-organizations/users.html#api-tokens) for the Terraform Cloud or Terraform Enterprise instance being used for testing. + +##### Optional: +1. `GITHUB_TOKEN` - [GitHub personal access token](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). Required for running OAuth client tests. +1. `GITHUB_POLICY_SET_IDENTIFIER` - GitHub policy set repository identifier in the format `username/repository`. Required for running policy set tests. + +You can set your environment variables up however you prefer. The following are instructions for setting up environment variables using [envchain](https://github.com/sorah/envchain). + 1. Make sure you have envchain installed. [Instructions for this can be found in the envchain README](https://github.com/sorah/envchain#installation). + 1. Pick a namespace for storing your environment variables. I suggest `go-tfe` or something similar. + 1. For each environment variable you need to set, run the following command: + ```sh + envchain --set YOUR_NAMESPACE_HERE ENVIRONMENT_VARIABLE_HERE + ``` + **OR** + + Set all of the environment variables at once with the following command: + ```sh + envchain --set YOUR_NAMESPACE_HERE TFE_ADDRESS TFE_TOKEN GITHUB_TOKEN GITHUB_POLICY_SET_IDENTIFIER + ``` + +### 3. Make sure run queue settings are correct + +In order for the tests relating to queuing and capacity to pass, FRQ (fair run queuing) should be +enabled with a limit of 2 concurrent runs per organization on the Terraform Cloud or Terraform Enterprise instance you are using for testing. + +### 4. Run the tests + +#### Running all the tests +As running the all of the tests takes about ~20 minutes, make sure to add a timeout to your +command (as the default timeout is 10m). +##### With envchain: ```sh -$ export TFE_ADDRESS=https://tfe.local -$ export TFE_TOKEN=xxxxxxxxxxxxxxxxxxx -$ export GITHUB_TOKEN=xxxxxxxxxxxxxxxx -$ export GITHUB_IDENTIFIER=xxxxxxxxxxx +$ envchain YOUR_NAMESPACE_HERE go test ./... -timeout=30m ``` -In order for the tests relating to queuing and capacity to pass, FRQ should be -enabled with a limit of 2 concurrent runs per organization. +##### Without envchain: +```sh +$ go test ./... -timeout=30m +``` +#### Running specific tests -As running the tests takes about ~10 minutes, make sure to add a timeout to your -command (as the default timeout is 10m): +The commands below use notification configurations as an example. +##### With envchain: ```sh -$ go test ./... -timeout=15m +$ envchain YOUR_NAMESPACE_HERE go test -run TestNotificationConfiguration -v ./... ``` +##### Without envchain: +```sh +$ go test -run TestNotificationConfiguration -v ./... +``` + ## Issues and Contributing If you find an issue with this package, please report an issue. If you'd like, we welcome any contributions. Fork this repository and submit a pull request. + +## Releases + +Documentation updates and test fixes that only touch test files don't require a release or tag. You can just merge these changes into master once they have been approved. + +### Creating a release +1. Merge your approved branch into master. +1. [Create a new release in GitHub](https://help.github.com/en/github/administering-a-repository/creating-releases). + - Click on "Releases" and then "Draft a new release" + - Set the `tag version` to a new tag, using [Semantic Versioning](https://semver.org/) as a guideline. + - Set the `target` as master. + - Set the `Release title` to the tag you created, `vX.Y.Z` + - Use the description section to describe why you're releasing and what changes you've made. You should include links to merged PRs + - Consider using the following headers in the description of your release: + - BREAKING CHANGES: Use this for any changes that aren't backwards compatible. Include details on how to handle these changes. + - FEATURES: Use this for any large new features added, + - ENHANCEMENTS: Use this for smaller new features added + - BUG FIXES: Use this for any bugs that were fixed. + - NOTES: Use this section if you need to include any additional notes on things like upgrading, upcoming deprecations, or any other information you might want to highlight. + + Markdown example: + + ```markdown + ENHANCEMENTS + * Add description of new small feature (#3)[link-to-pull-request] + + BUG FIXES + * Fix description of a bug (#2)[link-to-pull-request] + * Fix description of another bug (#1)[link-to-pull-request] + ``` + + - Don't attach any binaries. The zip and tar.gz assets are automatically created and attached after you publish your release. + - Click "Publish release" to save and publish your release. + \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/vendor/github.com/hashicorp/go-tfe/go.mod new/terraform-0.12.16/vendor/github.com/hashicorp/go-tfe/go.mod --- old/terraform-0.12.15/vendor/github.com/hashicorp/go-tfe/go.mod 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/vendor/github.com/hashicorp/go-tfe/go.mod 2019-11-18 23:09:27.000000000 +0100 @@ -5,7 +5,7 @@ github.com/google/go-querystring v1.0.0 github.com/hashicorp/go-cleanhttp v0.5.0 github.com/hashicorp/go-retryablehttp v0.5.2 - github.com/hashicorp/go-slug v0.4.0 + github.com/hashicorp/go-slug v0.4.1 github.com/hashicorp/go-uuid v1.0.1 github.com/stretchr/testify v1.3.0 github.com/svanharmelen/jsonapi v0.0.0-20180618144545-0c0828c3f16d diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/vendor/github.com/hashicorp/go-tfe/go.sum new/terraform-0.12.16/vendor/github.com/hashicorp/go-tfe/go.sum --- old/terraform-0.12.15/vendor/github.com/hashicorp/go-tfe/go.sum 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/vendor/github.com/hashicorp/go-tfe/go.sum 2019-11-18 23:09:27.000000000 +0100 @@ -10,6 +10,10 @@ github.com/hashicorp/go-retryablehttp v0.5.2/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-slug v0.4.0 h1:YSz3afoEZZJVVB46NITf0+opd2cHpaYJ1XSojOyP0x8= github.com/hashicorp/go-slug v0.4.0/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8= +github.com/hashicorp/go-slug v0.4.1-0.20191114211806-d9ee9eb3692a h1:EmBGX5Ja8JEKRHqTDG9+PYq0qL5qyOUmPZFQfH7VfXo= +github.com/hashicorp/go-slug v0.4.1-0.20191114211806-d9ee9eb3692a/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8= +github.com/hashicorp/go-slug v0.4.1 h1:/jAo8dNuLgSImoLXaX7Od7QB4TfYCVPam+OpAt5bZqc= +github.com/hashicorp/go-slug v0.4.1/go.mod h1:I5tq5Lv0E2xcNXNkmx7BSfzi1PsJ2cNjs3cC3LwyhK8= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/vendor/github.com/hashicorp/go-tfe/oauth_client.go new/terraform-0.12.16/vendor/github.com/hashicorp/go-tfe/oauth_client.go --- old/terraform-0.12.15/vendor/github.com/hashicorp/go-tfe/oauth_client.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/vendor/github.com/hashicorp/go-tfe/oauth_client.go 2019-11-18 23:09:27.000000000 +0100 @@ -40,13 +40,18 @@ // List of available VCS types. const ( - ServiceProviderBitbucket ServiceProviderType = "bitbucket_hosted" + ServiceProviderAzureDevOpsServer ServiceProviderType = "ado_server" + ServiceProviderAzureDevOpsServices ServiceProviderType = "ado_services" + ServiceProviderBitbucket ServiceProviderType = "bitbucket_hosted" + // Bitbucket Server v5.4.0 and above ServiceProviderBitbucketServer ServiceProviderType = "bitbucket_server" - ServiceProviderGithub ServiceProviderType = "github" - ServiceProviderGithubEE ServiceProviderType = "github_enterprise" - ServiceProviderGitlab ServiceProviderType = "gitlab_hosted" - ServiceProviderGitlabCE ServiceProviderType = "gitlab_community_edition" - ServiceProviderGitlabEE ServiceProviderType = "gitlab_enterprise_edition" + // Bitbucket Server v5.3.0 and below + ServiceProviderBitbucketServerLegacy ServiceProviderType = "bitbucket_server_legacy" + ServiceProviderGithub ServiceProviderType = "github" + ServiceProviderGithubEE ServiceProviderType = "github_enterprise" + ServiceProviderGitlab ServiceProviderType = "gitlab_hosted" + ServiceProviderGitlabCE ServiceProviderType = "gitlab_community_edition" + ServiceProviderGitlabEE ServiceProviderType = "gitlab_enterprise_edition" ) // OAuthClientList represents a list of OAuth clients. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/vendor/modules.txt new/terraform-0.12.16/vendor/modules.txt --- old/terraform-0.12.15/vendor/modules.txt 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/vendor/modules.txt 2019-11-18 23:09:27.000000000 +0100 @@ -316,9 +316,9 @@ github.com/hashicorp/go-rootcerts # github.com/hashicorp/go-safetemp v1.0.0 github.com/hashicorp/go-safetemp -# github.com/hashicorp/go-slug v0.4.0 +# github.com/hashicorp/go-slug v0.4.1 github.com/hashicorp/go-slug -# github.com/hashicorp/go-tfe v0.3.25 +# github.com/hashicorp/go-tfe v0.3.27 github.com/hashicorp/go-tfe # github.com/hashicorp/go-uuid v1.0.1 github.com/hashicorp/go-uuid diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/version/version.go new/terraform-0.12.16/version/version.go --- old/terraform-0.12.15/version/version.go 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/version/version.go 2019-11-18 23:09:27.000000000 +0100 @@ -11,7 +11,7 @@ ) // The main version number that is being run at the moment. -var Version = "0.12.15" +var Version = "0.12.16" // 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/website/docs/configuration/functions/trim.html.md new/terraform-0.12.16/website/docs/configuration/functions/trim.html.md --- old/terraform-0.12.15/website/docs/configuration/functions/trim.html.md 1970-01-01 01:00:00.000000000 +0100 +++ new/terraform-0.12.16/website/docs/configuration/functions/trim.html.md 2019-11-18 23:09:27.000000000 +0100 @@ -0,0 +1,31 @@ +--- +layout: "functions" +page_title: "trim - Functions - Configuration Language" +sidebar_current: "docs-funcs-string-trim" +description: |- + The trim function removes the specified characters from the start and end of + a given string. +--- + +# `trim` Function + +-> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and +earlier, see +[0.11 Configuration Language: Interpolation Syntax](../../configuration-0-11/interpolation.html). + +`trim` removes the specified characters from the start and end of the given +string. + +## Examples + +``` +> trim("?!hello?!", "!?") +hello +``` + +## Related Functions + +* [`trimprefix`](./trimprefix.html) removes a word from the start of a string. +* [`trimsuffix`](./trimsuffix.html) removes a word from the end of a string. +* [`trimspace`](./trimspace.html) removes all types of whitespace from + both the start and the end of a string. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/website/docs/configuration/functions/trimprefix.html.md new/terraform-0.12.16/website/docs/configuration/functions/trimprefix.html.md --- old/terraform-0.12.15/website/docs/configuration/functions/trimprefix.html.md 1970-01-01 01:00:00.000000000 +0100 +++ new/terraform-0.12.16/website/docs/configuration/functions/trimprefix.html.md 2019-11-18 23:09:27.000000000 +0100 @@ -0,0 +1,30 @@ +--- +layout: "functions" +page_title: "trimprefix - Functions - Configuration Language" +sidebar_current: "docs-funcs-string-trimprefix" +description: |- + The trimprefix function removes the specified prefix from the start of a + given string. +--- + +# `trimprefix` Function + +-> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and +earlier, see +[0.11 Configuration Language: Interpolation Syntax](../../configuration-0-11/interpolation.html). + +`trimprefix` removes the specified prefix from the start of the given string. + +## Examples + +``` +> trimprefix("helloworld", "hello") +world +``` + +## Related Functions + +* [`trim`](./trim.html) removes characters at the start and end of a string. +* [`trimsuffix`](./trimsuffix.html) removes a word from the end of a string. +* [`trimspace`](./trimspace.html) removes all types of whitespace from + both the start and the end of a string. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/website/docs/configuration/functions/trimsuffix.html.md new/terraform-0.12.16/website/docs/configuration/functions/trimsuffix.html.md --- old/terraform-0.12.15/website/docs/configuration/functions/trimsuffix.html.md 1970-01-01 01:00:00.000000000 +0100 +++ new/terraform-0.12.16/website/docs/configuration/functions/trimsuffix.html.md 2019-11-18 23:09:27.000000000 +0100 @@ -0,0 +1,30 @@ +--- +layout: "functions" +page_title: "trimsuffix - Functions - Configuration Language" +sidebar_current: "docs-funcs-string-trimsuffix" +description: |- + The trimsuffix function removes the specified suffix from the end of a + given string. +--- + +# `trimsuffix` Function + +-> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and +earlier, see +[0.11 Configuration Language: Interpolation Syntax](../../configuration-0-11/interpolation.html). + +`trimsuffix` removes the specified suffix from the end of the given string. + +## Examples + +``` +> trimsuffix("helloworld", "world") +hello +``` + +## Related Functions + +* [`trim`](./trim.html) removes characters at the start and end of a string. +* [`trimprefix`](./trimprefix.html) removes a word from the start of a string. +* [`trimspace`](./trimspace.html) removes all types of whitespace from + both the start and the end of a string. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/website/docs/configuration-0-11/interpolation.html.md new/terraform-0.12.16/website/docs/configuration-0-11/interpolation.html.md --- old/terraform-0.12.15/website/docs/configuration-0-11/interpolation.html.md 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/website/docs/configuration-0-11/interpolation.html.md 2019-11-18 23:09:27.000000000 +0100 @@ -39,27 +39,27 @@ #### User map variables -The syntax is `var.MAP["KEY"]`. For example, `${var.amis["us-east-1"]}` +The syntax is `var.<MAP>["<KEY>"]`. For example, `${var.amis["us-east-1"]}` would get the value of the `us-east-1` key within the `amis` map variable. #### User list variables -The syntax is `"${var.LIST}"`. For example, `"${var.subnets}"` +The syntax is `"${var.<LIST>}"`. For example, `"${var.subnets}"` would get the value of the `subnets` list, as a list. You can also return list elements by index: `${var.subnets[idx]}`. #### Attributes of your own resource -The syntax is `self.ATTRIBUTE`. For example `${self.private_ip}` +The syntax is `self.<ATTRIBUTE>`. For example `${self.private_ip}` will interpolate that resource's private IP address. --> **Note**: The `self.ATTRIBUTE` syntax is only allowed and valid within +-> **Note**: The `self.<ATTRIBUTE>` syntax is only allowed and valid within provisioners. #### Attributes of other resources -The syntax is `TYPE.NAME.ATTRIBUTE`. For example, +The syntax is `<TYPE>.<NAME>.<ATTRIBUTE>`. For example, `${aws_instance.web.id}` will interpolate the ID attribute from the `aws_instance` resource named `web`. If the resource has a `count` attribute set, you can access individual attributes with a zero-based @@ -68,27 +68,27 @@ #### Attributes of a data source -The syntax is `data.TYPE.NAME.ATTRIBUTE`. For example. `${data.aws_ami.ubuntu.id}` will interpolate the `id` attribute from the `aws_ami` [data source](./data-sources.html) named `ubuntu`. If the data source has a `count` +The syntax is `data.<TYPE>.<NAME>.<ATTRIBUTE>`. For example. `${data.aws_ami.ubuntu.id}` will interpolate the `id` attribute from the `aws_ami` [data source](./data-sources.html) named `ubuntu`. If the data source has a `count` attribute set, you can access individual attributes with a zero-based index, such as `${data.aws_subnet.example.0.cidr_block}`. You can also use the splat syntax to get a list of all the attributes: `${data.aws_subnet.example.*.cidr_block}`. #### Outputs from a module -The syntax is `MODULE.NAME.OUTPUT`. For example `${module.foo.bar}` will +The syntax is `module.<NAME>.<OUTPUT>`. For example `${module.foo.bar}` will interpolate the `bar` output from the `foo` [module](/docs/modules/index.html). #### Count information -The syntax is `count.FIELD`. For example, `${count.index}` will +The syntax is `count.index`. For example, `${count.index}` will interpolate the current index in a multi-count resource. For more information on `count`, see the [resource configuration page](./resources.html). #### Path information -The syntax is `path.TYPE`. TYPE can be `cwd`, `module`, or `root`. +The syntax is `path.<TYPE>`. TYPE can be `cwd`, `module`, or `root`. `cwd` will interpolate the current working directory. `module` will interpolate the path to the current module. `root` will interpolate the path of the root module. In general, you probably want the @@ -96,7 +96,7 @@ #### Terraform meta information -The syntax is `terraform.FIELD`. This variable type contains metadata about +The syntax is `terraform.<FIELD>`. This variable type contains metadata about the currently executing Terraform run. FIELD can currently only be `env` to reference the currently active [state environment](/docs/state/environments.html). @@ -146,7 +146,7 @@ syntax `name(arg, arg2, ...)`. For example, to read a file: `${file("path.txt")}`. -~> **NOTE**: Proper escaping is required for JSON field values containing quotes +~> **Note**: Proper escaping is required for JSON field values containing quotes (`"`) such as `environment` values. If directly setting the JSON, they should be escaped as `\"` in the JSON, e.g. `"value": "I \"love\" escaped quotes"`. If using a Terraform variable value, they should be escaped as `\\\"` in the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/terraform-0.12.15/website/layouts/functions.erb new/terraform-0.12.16/website/layouts/functions.erb --- old/terraform-0.12.15/website/layouts/functions.erb 2019-11-15 00:04:48.000000000 +0100 +++ new/terraform-0.12.16/website/layouts/functions.erb 2019-11-18 23:09:27.000000000 +0100 @@ -112,6 +112,18 @@ </li> <li> + <a href="/docs/configuration/functions/trim.html">trim</a> + </li> + + <li> + <a href="/docs/configuration/functions/trimprefix.html">trimprefix</a> + </li> + + <li> + <a href="/docs/configuration/functions/trimsuffix.html">trimsuffix</a> + </li> + + <li> <a href="/docs/configuration/functions/trimspace.html">trimspace</a> </li> ++++++ terraform.obsinfo ++++++ --- /var/tmp/diff_new_pack.SHsbNT/_old 2019-11-21 13:00:16.566498136 +0100 +++ /var/tmp/diff_new_pack.SHsbNT/_new 2019-11-21 13:00:16.566498136 +0100 @@ -1,5 +1,5 @@ name: terraform -version: 0.12.15 -mtime: 1573772688 -commit: 30637c9c901e23c8bda6ded7a714b663c663a3a9 +version: 0.12.16 +mtime: 1574114967 +commit: d54ddd5dc930cb3c926c37a1f4f5fb6eaae9b7bb
