summarylogtreecommitdiffstats
path: root/terraform-nowarning.patch
diff options
context:
space:
mode:
Diffstat (limited to 'terraform-nowarning.patch')
-rw-r--r--terraform-nowarning.patch375
1 files changed, 375 insertions, 0 deletions
diff --git a/terraform-nowarning.patch b/terraform-nowarning.patch
new file mode 100644
index 000000000000..69f99d2f62fa
--- /dev/null
+++ b/terraform-nowarning.patch
@@ -0,0 +1,375 @@
+From 88dae43732b76206548ca5b9f7cacb203411b3e0 Mon Sep 17 00:00:00 2001
+From: Eugene Dementyev <eugene@springload.co.nz>
+Date: Tue, 25 Jun 2019 14:10:41 +1200
+Subject: [PATCH] Allows undeclares variables
+
+---
+ backend/damerau_levenshtein.go | 132 +++++++++++++++++++++++++++++++++
+ backend/unparsed_value.go | 68 ++++++++++-------
+ backend/unparsed_value_test.go | 50 ++++++++-----
+ 3 files changed, 206 insertions(+), 44 deletions(-)
+ create mode 100644 backend/damerau_levenshtein.go
+
+diff --git a/backend/damerau_levenshtein.go b/backend/damerau_levenshtein.go
+new file mode 100644
+index 000000000..5ee1d2c76
+--- /dev/null
++++ b/backend/damerau_levenshtein.go
+@@ -0,0 +1,132 @@
++package backend
++
++import "math"
++
++// References:
++// This is based off https://github.com/antzucaro/matchr which itself is
++// based off of the one found on Wikipedia at
++// http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance#Distance_with_adjacent_transpositions
++// as well as KevinStern's Java implementation found at
++// https://github.com/KevinStern/software-and-algorithms.
++func DamerauLevenshtein(s1, s2 string) (distance int) {
++ // index by code point, not byte
++ r1 := []rune(s1)
++ r2 := []rune(s2)
++
++ // the maximum possible distance
++ inf := len(r1) + len(r2)
++
++ // if one string is blank, we needs insertions
++ // for all characters in the other one
++ if len(r1) == 0 {
++ return len(r2)
++ }
++
++ if len(r2) == 0 {
++ return len(r1)
++ }
++
++ // construct the edit-tracking matrix
++ matrix := make([][]int, len(r1))
++ for i := range matrix {
++ matrix[i] = make([]int, len(r2))
++ }
++
++ // seen characters
++ seenRunes := make(map[rune]int)
++
++ if r1[0] != r2[0] {
++ matrix[0][0] = 1
++ }
++
++ seenRunes[r1[0]] = 0
++ for i := 1; i < len(r1); i++ {
++ deleteDist := matrix[i-1][0] + 1
++ insertDist := (i+1)*1 + 1
++ var matchDist int
++ if r1[i] == r2[0] {
++ matchDist = i
++ } else {
++ matchDist = i + 1
++ }
++ matrix[i][0] = minInt32(minInt32(deleteDist, insertDist), matchDist)
++ }
++
++ for j := 1; j < len(r2); j++ {
++ deleteDist := (j + 1) * 2
++ insertDist := matrix[0][j-1] + 1
++ var matchDist int
++ if r1[0] == r2[j] {
++ matchDist = j
++ } else {
++ matchDist = j + 1
++ }
++
++ matrix[0][j] = minInt32(minInt32(deleteDist, insertDist), matchDist)
++ }
++
++ for i := 1; i < len(r1); i++ {
++ var maxSrcMatchIndex int
++ if r1[i] == r2[0] {
++ maxSrcMatchIndex = 0
++ } else {
++ maxSrcMatchIndex = -1
++ }
++
++ for j := 1; j < len(r2); j++ {
++ swapIndex, ok := seenRunes[r2[j]]
++ jSwap := maxSrcMatchIndex
++ deleteDist := matrix[i-1][j] + 1
++ insertDist := matrix[i][j-1] + 1
++ matchDist := matrix[i-1][j-1]
++ if r1[i] != r2[j] {
++ matchDist++
++ } else {
++ maxSrcMatchIndex = j
++ }
++
++ // for transpositions
++ var swapDist int
++ if ok && jSwap != -1 {
++ iSwap := swapIndex
++ var preSwapCost int
++ if iSwap == 0 && jSwap == 0 {
++ preSwapCost = 0
++ } else {
++ preSwapCost = matrix[maxInt32(0, iSwap-1)][maxInt32(0, jSwap-1)]
++ }
++ swapDist = i + j + preSwapCost - iSwap - jSwap - 1
++ } else {
++ swapDist = inf
++ }
++ matrix[i][j] = minInt32(minInt32(minInt32(deleteDist, insertDist), matchDist), swapDist)
++ }
++ seenRunes[r1[i]] = i
++ }
++
++ return matrix[len(r1)-1][len(r2)-1]
++}
++
++// minInt32 finds the minimum int32 value of a range of int.
++// MinInt32 = -1 << 31
++func minInt32(a ...int) int {
++ min := math.MaxInt32
++ for _, i := range a {
++ if i < min {
++ min = i
++ }
++ }
++ return min
++}
++
++// maxInt32 finds the maximum int32 value of a range of int.
++// MaxInt32 = 1<<31 - 1
++func maxInt32(a ...int) int {
++ max := math.MinInt32
++ for _, i := range a {
++ if i > max {
++ max = i
++ }
++ }
++ return max
++}
+diff --git a/backend/unparsed_value.go b/backend/unparsed_value.go
+index 65a05c823..fcb5c966c 100644
+--- a/backend/unparsed_value.go
++++ b/backend/unparsed_value.go
+@@ -2,8 +2,9 @@ package backend
+
+ import (
+ "fmt"
++ "strings"
+
+- "github.com/hashicorp/hcl/v2"
++ hcl "github.com/hashicorp/hcl/v2"
+ "github.com/hashicorp/terraform/configs"
+ "github.com/hashicorp/terraform/terraform"
+ "github.com/hashicorp/terraform/tfdiags"
+@@ -44,6 +45,10 @@ type UnparsedVariableValue interface {
+ func ParseVariableValues(vv map[string]UnparsedVariableValue, decls map[string]*configs.Variable) (terraform.InputValues, tfdiags.Diagnostics) {
+ var diags tfdiags.Diagnostics
+ ret := make(terraform.InputValues, len(vv))
++ var variables []string
++ for v, _ := range decls {
++ variables = append(variables, v)
++ }
+
+ // Currently we're generating only warnings for undeclared variables
+ // defined in files (see below) but we only want to generate a few warnings
+@@ -52,6 +57,7 @@ func ParseVariableValues(vv map[string]UnparsedVariableValue, decls map[string]*
+ seenUndeclaredInFile := 0
+
+ for name, rv := range vv {
++ name := name
+ var mode configs.VariableParsingMode
+ config, declared := decls[name]
+ if declared {
+@@ -69,30 +75,38 @@ func ParseVariableValues(vv map[string]UnparsedVariableValue, decls map[string]*
+ if !declared {
+ switch val.SourceType {
+ case terraform.ValueFromConfig, terraform.ValueFromAutoFile, terraform.ValueFromNamedFile:
+- // These source types have source ranges, so we can produce
+- // a nice error message with good context.
+- //
+- // This one is a warning for now because there is an existing
+- // pattern of providing a file containing the superset of
+- // variables across all configurations in an organization. This
+- // is deprecated in v0.12.0 because it's more important to give
+- // feedback to users who make typos. Those using this approach
+- // should migrate to using environment variables instead before
+- // this becomes an error in a future major release.
+- if seenUndeclaredInFile < 3 {
+- diags = diags.Append(tfdiags.Sourceless(
+- tfdiags.Warning,
+- "Value for undeclared variable",
+- fmt.Sprintf("The root module does not declare a variable named %q but a value was found in file %q. To use this value, add a \"variable\" block to the configuration.\n\nUsing a variables file to set an undeclared variable is deprecated and will become an error in a future release. If you wish to provide certain \"global\" settings to all configurations in your organization, use TF_VAR_... environment variables to set these instead.", name, val.SourceRange.Filename),
+- ))
++ var matches []string
++ for _, declaredVariable := range variables {
++ if DamerauLevenshtein(name, declaredVariable) <= 2 {
++ matches = append(matches, declaredVariable)
++ }
++ }
++ if len(matches) > 0 {
++ // These source types have source ranges, so we can produce
++ // a nice error message with good context.
++ //
++ // This one is a warning for now because there is an existing
++ // pattern of providing a file containing the superset of
++ // variables across all configurations in an organization. This
++ // is deprecated in v0.12.0 because it's more important to give
++ // feedback to users who make typos. Those using this approach
++ // should migrate to using environment variables instead before
++ // this becomes an error in a future major release.
++ if seenUndeclaredInFile < 3 {
++ diags = diags.Append(tfdiags.Sourceless(
++ tfdiags.Warning,
++ "Value for undeclared variable",
++ fmt.Sprintf("The root module does not declare a variable named %q. Did you mean one of [%s]?", name, strings.Join(matches, ", ")),
++ ))
++ }
++ seenUndeclaredInFile++
+ }
+- seenUndeclaredInFile++
+
+ case terraform.ValueFromEnvVar:
+- // We allow and ignore undeclared names for environment
+- // variables, because users will often set these globally
+- // when they are used across many (but not necessarily all)
+- // configurations.
++ // We allow and ignore undeclared names for environment
++ // variables, because users will often set these globally
++ // when they are used across many (but not necessarily all)
++ // configurations.
+ case terraform.ValueFromCLIArg:
+ diags = diags.Append(tfdiags.Sourceless(
+ tfdiags.Error,
+@@ -116,11 +130,11 @@ func ParseVariableValues(vv map[string]UnparsedVariableValue, decls map[string]*
+
+ if seenUndeclaredInFile >= 3 {
+ extras := seenUndeclaredInFile - 2
+- diags = diags.Append(&hcl.Diagnostic{
+- Severity: hcl.DiagWarning,
+- Summary: "Values for undeclared variables",
+- Detail: fmt.Sprintf("In addition to the other similar warnings shown, %d other variable(s) defined without being declared.", extras),
+- })
++ diags = diags.Append(tfdiags.Sourceless(
++ tfdiags.Warning,
++ "Values for undeclared variables",
++ fmt.Sprintf("In addition to the other similar warnings shown, %d other variable(s) defined without being declared.", extras),
++ ))
+ }
+
+ // By this point we should've gathered all of the required root module
+diff --git a/backend/unparsed_value_test.go b/backend/unparsed_value_test.go
+index 27fba6257..d51575480 100644
+--- a/backend/unparsed_value_test.go
++++ b/backend/unparsed_value_test.go
+@@ -1,10 +1,11 @@
+ package backend
+
+ import (
++ "math/big"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+- "github.com/hashicorp/hcl/v2"
++ hcl "github.com/hashicorp/hcl/v2"
+ "github.com/zclconf/go-cty/cty"
+
+ "github.com/hashicorp/terraform/configs"
+@@ -14,12 +15,13 @@ import (
+
+ func TestParseVariableValuesUndeclared(t *testing.T) {
+ vv := map[string]UnparsedVariableValue{
+- "undeclared0": testUnparsedVariableValue("0"),
+- "undeclared1": testUnparsedVariableValue("1"),
+- "undeclared2": testUnparsedVariableValue("2"),
+- "undeclared3": testUnparsedVariableValue("3"),
+- "undeclared4": testUnparsedVariableValue("4"),
+- "declared1": testUnparsedVariableValue("5"),
++ "undeclared0": testUnparsedVariableValue("0"),
++ "undeclared1": testUnparsedVariableValue("1"),
++ "undeclared2": testUnparsedVariableValue("2"),
++ "undeclared3": testUnparsedVariableValue("3"),
++ "undeclared4": testUnparsedVariableValue("4"),
++ "declared1": testUnparsedVariableValue("5"),
++ "load_balancer_lstener_port": testUnparsedVariableValue("6"),
+ }
+ decls := map[string]*configs.Variable{
+ "declared1": {
+@@ -43,7 +45,7 @@ func TestParseVariableValuesUndeclared(t *testing.T) {
+ },
+ },
+ "missing2": {
+- Name: "missing1",
++ Name: "missing2",
+ Type: cty.String,
+ ParsingMode: configs.VariableParseLiteral,
+ Default: cty.StringVal("default for missing2"),
+@@ -53,18 +55,29 @@ func TestParseVariableValuesUndeclared(t *testing.T) {
+ End: hcl.Pos{Line: 4, Column: 1, Byte: 0},
+ },
+ },
++ "load_balancer_listener_port": {
++ Name: "load_balancer_listener_port",
++ Type: cty.Number,
++ ParsingMode: configs.VariableParseLiteral,
++ Default: cty.NumberVal(big.NewFloat(8080.)),
++ DeclRange: hcl.Range{
++ Filename: "fake.tf",
++ Start: hcl.Pos{Line: 5, Column: 1, Byte: 0},
++ End: hcl.Pos{Line: 5, Column: 1, Byte: 0},
++ },
++ },
+ }
+
+ gotVals, diags := ParseVariableValues(vv, decls)
++
+ for _, diag := range diags {
+ t.Logf("%s: %s", diag.Description().Summary, diag.Description().Detail)
+ }
+- if got, want := len(diags), 5; got != want {
++ if got, want := len(diags), 3; got != want {
+ t.Fatalf("wrong number of diagnostics %d; want %d", got, want)
+ }
+
+ const undeclSingular = `Value for undeclared variable`
+- const undeclPlural = `Values for undeclared variables`
+ const missingRequired = `No value for required variable`
+
+ if got, want := diags[0].Description().Summary, undeclSingular; got != want {
+@@ -73,15 +86,9 @@ func TestParseVariableValuesUndeclared(t *testing.T) {
+ if got, want := diags[1].Description().Summary, undeclSingular; got != want {
+ t.Errorf("wrong summary for diagnostic 1\ngot: %s\nwant: %s", got, want)
+ }
+- if got, want := diags[2].Description().Summary, undeclSingular; got != want {
++ if got, want := diags[2].Description().Summary, missingRequired; got != want {
+ t.Errorf("wrong summary for diagnostic 2\ngot: %s\nwant: %s", got, want)
+ }
+- if got, want := diags[3].Description().Summary, undeclPlural; got != want {
+- t.Errorf("wrong summary for diagnostic 3\ngot: %s\nwant: %s", got, want)
+- }
+- if got, want := diags[4].Description().Summary, missingRequired; got != want {
+- t.Errorf("wrong summary for diagnostic 4\ngot: %s\nwant: %s", got, want)
+- }
+
+ wantVals := terraform.InputValues{
+ "declared1": {
+@@ -111,6 +118,15 @@ func TestParseVariableValuesUndeclared(t *testing.T) {
+ End: tfdiags.SourcePos{Line: 4, Column: 1, Byte: 0},
+ },
+ },
++ "load_balancer_listener_port": {
++ Value: cty.NumberVal(big.NewFloat(8080.)),
++ SourceType: terraform.ValueFromConfig,
++ SourceRange: tfdiags.SourceRange{
++ Filename: "fake.tf",
++ Start: tfdiags.SourcePos{Line: 5, Column: 1, Byte: 0},
++ End: tfdiags.SourcePos{Line: 5, Column: 1, Byte: 0},
++ },
++ },
+ }
+ if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" {
+ t.Errorf("wrong result\n%s", diff)
+--
+2.30.0
+