diff --git a/GNUmakefile b/GNUmakefile index a8df79344ef..6a4e4ae3c89 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -102,6 +102,9 @@ lint: -S032 \ -S033 \ -S034 \ + -S035 \ + -S036 \ + -S037 \ -V002 \ -V003 \ -V004 \ diff --git a/go.mod b/go.mod index c8fb6a19617..9632ceb12c7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/aws/aws-sdk-go v1.29.24 github.com/beevik/etree v1.1.0 github.com/bflad/tfproviderdocs v0.5.0 - github.com/bflad/tfproviderlint v0.11.0 + github.com/bflad/tfproviderlint v0.12.0 github.com/client9/misspell v0.3.4 github.com/golangci/golangci-lint v1.23.8 github.com/hashicorp/aws-sdk-go-base v0.4.0 diff --git a/go.sum b/go.sum index 8a8ec1e5c26..fa3ca95338d 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,8 @@ github.com/bflad/gopaniccheck v0.1.0 h1:tJftp+bv42ouERmUMWLoUn/5bi/iQZjHPznM00cP github.com/bflad/gopaniccheck v0.1.0/go.mod h1:ZCj2vSr7EqVeDaqVsWN4n2MwdROx1YL+LFo47TSWtsA= github.com/bflad/tfproviderdocs v0.5.0 h1:FzT4hEtKX1WcrLmZSRB83kFdzRmkqu7kS9RHn5oKAuA= github.com/bflad/tfproviderdocs v0.5.0/go.mod h1:d0k1fQLEu1pdeORxozwuwmvauFaEmMBREQ1fw3J+pPc= -github.com/bflad/tfproviderlint v0.11.0 h1:+yxfoHoOhg8h/oNSf7YwNDs/ztAJZPXIpx4IQwrjMUg= -github.com/bflad/tfproviderlint v0.11.0/go.mod h1:MsNI3eEj7uC7P/h7XmGvzMLtsotLkrvB+NF2/w3RZGc= +github.com/bflad/tfproviderlint v0.12.0 h1:vAl/8VOk/o3jEBbyMkWHrkCa6sisT4INDMCkXu0GNDw= +github.com/bflad/tfproviderlint v0.12.0/go.mod h1:MsNI3eEj7uC7P/h7XmGvzMLtsotLkrvB+NF2/w3RZGc= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas= github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= diff --git a/vendor/github.com/bflad/tfproviderlint/helper/analysisutils/schema_analyzers.go b/vendor/github.com/bflad/tfproviderlint/helper/analysisutils/schema_analyzers.go new file mode 100644 index 00000000000..396148ce2c3 --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/helper/analysisutils/schema_analyzers.go @@ -0,0 +1,29 @@ +package analysisutils + +import ( + "fmt" + + "github.com/bflad/tfproviderlint/passes/commentignore" + "github.com/bflad/tfproviderlint/passes/helper/schema/schemainfo" + "golang.org/x/tools/go/analysis" +) + +// SchemaAttributeReferencesAnalyzer returns an Analyzer for fields that use schema attribute references +func SchemaAttributeReferencesAnalyzer(analyzerName string, fieldName string) *analysis.Analyzer { + doc := fmt.Sprintf(`check for Schema with invalid %[2]s references + +The %[1]s analyzer ensures schema attribute references in the Schema %[2]s +field use valid syntax. The Terraform Plugin SDK can unit test attribute +references to verify the references against the full schema. +`, analyzerName, fieldName) + + return &analysis.Analyzer{ + Name: analyzerName, + Doc: doc, + Requires: []*analysis.Analyzer{ + commentignore.Analyzer, + schemainfo.Analyzer, + }, + Run: SchemaAttributeReferencesRunner(analyzerName, fieldName), + } +} diff --git a/vendor/github.com/bflad/tfproviderlint/helper/analysisutils/schema_runners.go b/vendor/github.com/bflad/tfproviderlint/helper/analysisutils/schema_runners.go new file mode 100644 index 00000000000..fde4b9ab18c --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/helper/analysisutils/schema_runners.go @@ -0,0 +1,50 @@ +package analysisutils + +import ( + "go/ast" + + "github.com/bflad/tfproviderlint/helper/astutils" + "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" + "github.com/bflad/tfproviderlint/passes/commentignore" + "github.com/bflad/tfproviderlint/passes/helper/schema/schemainfo" + "golang.org/x/tools/go/analysis" +) + +// SchemaAttributeReferencesRunner returns an Analyzer runner for fields that use schema attribute references +func SchemaAttributeReferencesRunner(analyzerName string, fieldName string) func(*analysis.Pass) (interface{}, error) { + return func(pass *analysis.Pass) (interface{}, error) { + ignorer := pass.ResultOf[commentignore.Analyzer].(*commentignore.Ignorer) + schemaInfos := pass.ResultOf[schemainfo.Analyzer].([]*schema.SchemaInfo) + + for _, schemaInfo := range schemaInfos { + if ignorer.ShouldIgnore(analyzerName, schemaInfo.AstCompositeLit) { + continue + } + + if !schemaInfo.DeclaresField(fieldName) { + continue + } + + switch value := schemaInfo.Fields[fieldName].Value.(type) { + case *ast.CompositeLit: + if !astutils.IsExprTypeArrayString(value.Type) { + continue + } + + for _, elt := range value.Elts { + attributeReference := astutils.ExprStringValue(elt) + + if attributeReference == nil { + continue + } + + if _, err := schema.ParseAttributeReference(*attributeReference); err != nil { + pass.Reportf(elt.Pos(), "%s: invalid %s attribute reference: %s", analyzerName, fieldName, err) + } + } + } + } + + return nil, nil + } +} diff --git a/vendor/github.com/bflad/tfproviderlint/helper/astutils/expr.go b/vendor/github.com/bflad/tfproviderlint/helper/astutils/expr.go new file mode 100644 index 00000000000..ebd012d0398 --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/helper/astutils/expr.go @@ -0,0 +1,40 @@ +package astutils + +import ( + "go/ast" +) + +// IsExprTypeArrayString returns true if the expression matches []string +func IsExprTypeArrayString(e ast.Expr) bool { + arrayType, ok := e.(*ast.ArrayType) + + return ok && IsExprTypeString(arrayType.Elt) +} + +// IsExprTypeArrayError returns true if the expression matches []error +func IsExprTypeArrayError(e ast.Expr) bool { + arrayType, ok := e.(*ast.ArrayType) + + return ok && IsExprTypeError(arrayType.Elt) +} + +// IsExprTypeError returns true if the expression matches string +func IsExprTypeError(e ast.Expr) bool { + ident, ok := e.(*ast.Ident) + + return ok && ident.Name == "error" +} + +// IsExprTypeInterface returns true if the expression matches interface{} +func IsExprTypeInterface(e ast.Expr) bool { + _, ok := e.(*ast.InterfaceType) + + return ok +} + +// IsExprTypeString returns true if the expression matches string +func IsExprTypeString(e ast.Expr) bool { + ident, ok := e.(*ast.Ident) + + return ok && ident.Name == "string" +} diff --git a/vendor/github.com/bflad/tfproviderlint/helper/astutils/function_parameters.go b/vendor/github.com/bflad/tfproviderlint/helper/astutils/function_parameters.go deleted file mode 100644 index 941b88dcc50..00000000000 --- a/vendor/github.com/bflad/tfproviderlint/helper/astutils/function_parameters.go +++ /dev/null @@ -1,40 +0,0 @@ -package astutils - -import ( - "go/ast" -) - -// IsFunctionParameterTypeArrayString returns true if the expression matches []string -func IsFunctionParameterTypeArrayString(e ast.Expr) bool { - arrayType, ok := e.(*ast.ArrayType) - - return ok && IsFunctionParameterTypeString(arrayType.Elt) -} - -// IsFunctionParameterTypeArrayError returns true if the expression matches []error -func IsFunctionParameterTypeArrayError(e ast.Expr) bool { - arrayType, ok := e.(*ast.ArrayType) - - return ok && IsFunctionParameterTypeError(arrayType.Elt) -} - -// IsFunctionParameterTypeError returns true if the expression matches string -func IsFunctionParameterTypeError(e ast.Expr) bool { - ident, ok := e.(*ast.Ident) - - return ok && ident.Name == "error" -} - -// IsFunctionParameterTypeInterface returns true if the expression matches interface{} -func IsFunctionParameterTypeInterface(e ast.Expr) bool { - _, ok := e.(*ast.InterfaceType) - - return ok -} - -// IsFunctionParameterTypeString returns true if the expression matches string -func IsFunctionParameterTypeString(e ast.Expr) bool { - ident, ok := e.(*ast.Ident) - - return ok && ident.Name == "string" -} diff --git a/vendor/github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema/attributes.go b/vendor/github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema/attributes.go new file mode 100644 index 00000000000..8888276a710 --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema/attributes.go @@ -0,0 +1,61 @@ +package schema + +import ( + "fmt" + "math" + "regexp" + "strconv" + "strings" +) + +const ( + // Pattern for schema attribute names + AttributeNameRegexpPattern = `^[a-z0-9_]+$` + + // Pattern for schema references to attributes, such as ConflictsWith values + AttributeReferenceRegexpPattern = `^[a-z0-9_]+(\.[a-z0-9_]+)*$` +) + +var ( + AttributeNameRegexp = regexp.MustCompile(AttributeNameRegexpPattern) + AttributeReferenceRegexp = regexp.MustCompile(AttributeReferenceRegexpPattern) +) + +// ParseAttributeReference validates and returns the split representation of schema attribute reference. +// Attribute references are used in Schema fields such as AtLeastOneOf, ConflictsWith, and ExactlyOneOf. +func ParseAttributeReference(reference string) ([]string, error) { + if !AttributeReferenceRegexp.MatchString(reference) { + return nil, fmt.Errorf("%q must contain only valid attribute names, separated by periods", reference) + } + + attributeReferenceParts := strings.Split(reference, ".") + + if len(attributeReferenceParts) == 1 { + return attributeReferenceParts, nil + } + + configurationBlockReferenceErr := fmt.Errorf("%q configuration block attribute references are only valid for TypeList and MaxItems: 1 attributes and nested attributes must be separated by .0.", reference) + + if math.Mod(float64(len(attributeReferenceParts)), 2) == 0 { + return attributeReferenceParts, configurationBlockReferenceErr + } + + // All even parts of an attribute reference must be 0 + for idx, attributeReferencePart := range attributeReferenceParts { + if math.Mod(float64(idx), 2) == 0 { + continue + } + + attributeReferencePartInt, err := strconv.Atoi(attributeReferencePart) + + if err != nil { + return attributeReferenceParts, configurationBlockReferenceErr + } + + if attributeReferencePartInt != 0 { + return attributeReferenceParts, configurationBlockReferenceErr + } + } + + return attributeReferenceParts, nil +} diff --git a/vendor/github.com/bflad/tfproviderlint/passes/S015/S015.go b/vendor/github.com/bflad/tfproviderlint/passes/S015/S015.go index 1e62bd2dda8..9ecfe7bc347 100644 --- a/vendor/github.com/bflad/tfproviderlint/passes/S015/S015.go +++ b/vendor/github.com/bflad/tfproviderlint/passes/S015/S015.go @@ -5,7 +5,6 @@ package S015 import ( "go/ast" - "regexp" "strings" "golang.org/x/tools/go/analysis" @@ -37,8 +36,6 @@ func run(pass *analysis.Pass) (interface{}, error) { ignorer := pass.ResultOf[commentignore.Analyzer].(*commentignore.Ignorer) schemamapcompositelits := pass.ResultOf[schemamapcompositelit.Analyzer].([]*ast.CompositeLit) - attributeNameRegex := regexp.MustCompile(`^[a-z0-9_]+$`) - for _, smap := range schemamapcompositelits { if ignorer.ShouldIgnore(analyzerName, smap) { continue @@ -51,7 +48,7 @@ func run(pass *analysis.Pass) (interface{}, error) { case *ast.BasicLit: value := strings.Trim(t.Value, `"`) - if !attributeNameRegex.MatchString(value) { + if !schema.AttributeNameRegexp.MatchString(value) { pass.Reportf(t.Pos(), "%s: schema attribute names should only be lowercase alphanumeric characters or underscores", analyzerName) } } diff --git a/vendor/github.com/bflad/tfproviderlint/passes/S035/README.md b/vendor/github.com/bflad/tfproviderlint/passes/S035/README.md new file mode 100644 index 00000000000..28233004e70 --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/passes/S035/README.md @@ -0,0 +1,32 @@ +# S035 + +The S035 analyzer reports cases of Schemas which include `AtLeastOneOf` and have invalid schema attribute references. + +NOTE: This only verifies the syntax of attribute references. The Terraform Plugin SDK can unit test attribute references to verify the references against the full schema. + +## Flagged Code + +```go +&schema.Schema{ + AtLeastOneOf: []string{"config_block_attr.nested_attr"}, +} +``` + +## Passing Code + +```go +&schema.Schema{ + AtLeastOneOf: []string{"config_block_attr.0.nested_attr"}, +} +``` + +## Ignoring Reports + +Singular reports can be ignored by adding the a `//lintignore:S035` Go code comment at the end of the offending line or on the line immediately proceding, e.g. + +```go +//lintignore:S035 +&schema.Schema{ + AtLeastOneOf: []string{"config_block_attr.nested_attr"}, +} +``` diff --git a/vendor/github.com/bflad/tfproviderlint/passes/S035/S035.go b/vendor/github.com/bflad/tfproviderlint/passes/S035/S035.go new file mode 100644 index 00000000000..48a5747322e --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/passes/S035/S035.go @@ -0,0 +1,8 @@ +package S035 + +import ( + "github.com/bflad/tfproviderlint/helper/analysisutils" + "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" +) + +var Analyzer = analysisutils.SchemaAttributeReferencesAnalyzer("S035", schema.SchemaFieldAtLeastOneOf) diff --git a/vendor/github.com/bflad/tfproviderlint/passes/S036/README.md b/vendor/github.com/bflad/tfproviderlint/passes/S036/README.md new file mode 100644 index 00000000000..1b00945d4e6 --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/passes/S036/README.md @@ -0,0 +1,32 @@ +# S036 + +The S036 analyzer reports cases of Schemas which include `ConflictsWith` and have invalid schema attribute references. + +NOTE: This only verifies the syntax of attribute references. The Terraform Plugin SDK can unit test attribute references to verify the references against the full schema. + +## Flagged Code + +```go +&schema.Schema{ + ConflictsWith: []string{"config_block_attr.nested_attr"}, +} +``` + +## Passing Code + +```go +&schema.Schema{ + ConflictsWith: []string{"config_block_attr.0.nested_attr"}, +} +``` + +## Ignoring Reports + +Singular reports can be ignored by adding the a `//lintignore:S036` Go code comment at the end of the offending line or on the line immediately proceding, e.g. + +```go +//lintignore:S036 +&schema.Schema{ + ConflictsWith: []string{"config_block_attr.nested_attr"}, +} +``` diff --git a/vendor/github.com/bflad/tfproviderlint/passes/S036/S036.go b/vendor/github.com/bflad/tfproviderlint/passes/S036/S036.go new file mode 100644 index 00000000000..8121a618d72 --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/passes/S036/S036.go @@ -0,0 +1,8 @@ +package S036 + +import ( + "github.com/bflad/tfproviderlint/helper/analysisutils" + "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" +) + +var Analyzer = analysisutils.SchemaAttributeReferencesAnalyzer("S036", schema.SchemaFieldConflictsWith) diff --git a/vendor/github.com/bflad/tfproviderlint/passes/S037/README.md b/vendor/github.com/bflad/tfproviderlint/passes/S037/README.md new file mode 100644 index 00000000000..ff3ed84139f --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/passes/S037/README.md @@ -0,0 +1,32 @@ +# S037 + +The S037 analyzer reports cases of Schemas which include `ExactlyOneOf` and have invalid schema attribute references. + +NOTE: This only verifies the syntax of attribute references. The Terraform Plugin SDK can unit test attribute references to verify the references against the full schema. + +## Flagged Code + +```go +&schema.Schema{ + ExactlyOneOf: []string{"config_block_attr.nested_attr"}, +} +``` + +## Passing Code + +```go +&schema.Schema{ + ExactlyOneOf: []string{"config_block_attr.0.nested_attr"}, +} +``` + +## Ignoring Reports + +Singular reports can be ignored by adding the a `//lintignore:S037` Go code comment at the end of the offending line or on the line immediately proceding, e.g. + +```go +//lintignore:S037 +&schema.Schema{ + ExactlyOneOf: []string{"config_block_attr.nested_attr"}, +} +``` diff --git a/vendor/github.com/bflad/tfproviderlint/passes/S037/S037.go b/vendor/github.com/bflad/tfproviderlint/passes/S037/S037.go new file mode 100644 index 00000000000..aa9ebe5e135 --- /dev/null +++ b/vendor/github.com/bflad/tfproviderlint/passes/S037/S037.go @@ -0,0 +1,8 @@ +package S037 + +import ( + "github.com/bflad/tfproviderlint/helper/analysisutils" + "github.com/bflad/tfproviderlint/helper/terraformtype/helper/schema" +) + +var Analyzer = analysisutils.SchemaAttributeReferencesAnalyzer("S037", schema.SchemaFieldExactlyOneOf) diff --git a/vendor/github.com/bflad/tfproviderlint/passes/checks.go b/vendor/github.com/bflad/tfproviderlint/passes/checks.go index 76e26ee4594..e42e9570cb8 100644 --- a/vendor/github.com/bflad/tfproviderlint/passes/checks.go +++ b/vendor/github.com/bflad/tfproviderlint/passes/checks.go @@ -57,6 +57,9 @@ import ( "github.com/bflad/tfproviderlint/passes/S032" "github.com/bflad/tfproviderlint/passes/S033" "github.com/bflad/tfproviderlint/passes/S034" + "github.com/bflad/tfproviderlint/passes/S035" + "github.com/bflad/tfproviderlint/passes/S036" + "github.com/bflad/tfproviderlint/passes/S037" "github.com/bflad/tfproviderlint/passes/V001" "github.com/bflad/tfproviderlint/passes/V002" "github.com/bflad/tfproviderlint/passes/V003" @@ -128,6 +131,9 @@ var AllChecks = []*analysis.Analyzer{ S032.Analyzer, S033.Analyzer, S034.Analyzer, + S035.Analyzer, + S036.Analyzer, + S037.Analyzer, V001.Analyzer, V002.Analyzer, V003.Analyzer, diff --git a/vendor/github.com/bflad/tfproviderlint/passes/helper/schema/crudfuncinfo/crudfuncinfo.go b/vendor/github.com/bflad/tfproviderlint/passes/helper/schema/crudfuncinfo/crudfuncinfo.go index d176266b1ad..9ad00f0092c 100644 --- a/vendor/github.com/bflad/tfproviderlint/passes/helper/schema/crudfuncinfo/crudfuncinfo.go +++ b/vendor/github.com/bflad/tfproviderlint/passes/helper/schema/crudfuncinfo/crudfuncinfo.go @@ -40,11 +40,11 @@ func run(pass *analysis.Pass) (interface{}, error) { return } - if !astutils.IsFieldListType(funcType.Params, 1, astutils.IsFunctionParameterTypeInterface) { + if !astutils.IsFieldListType(funcType.Params, 1, astutils.IsExprTypeInterface) { return } - if !astutils.IsFieldListType(funcType.Results, 0, astutils.IsFunctionParameterTypeError) { + if !astutils.IsFieldListType(funcType.Results, 0, astutils.IsExprTypeError) { return } diff --git a/vendor/github.com/bflad/tfproviderlint/passes/helper/schema/schemavalidatefuncinfo/schemavalidatefuncinfo.go b/vendor/github.com/bflad/tfproviderlint/passes/helper/schema/schemavalidatefuncinfo/schemavalidatefuncinfo.go index 92c577e16dc..5af0f0b6beb 100644 --- a/vendor/github.com/bflad/tfproviderlint/passes/helper/schema/schemavalidatefuncinfo/schemavalidatefuncinfo.go +++ b/vendor/github.com/bflad/tfproviderlint/passes/helper/schema/schemavalidatefuncinfo/schemavalidatefuncinfo.go @@ -36,19 +36,19 @@ func run(pass *analysis.Pass) (interface{}, error) { return } - if !astutils.IsFieldListType(funcType.Params, 0, astutils.IsFunctionParameterTypeInterface) { + if !astutils.IsFieldListType(funcType.Params, 0, astutils.IsExprTypeInterface) { return } - if !astutils.IsFieldListType(funcType.Params, 1, astutils.IsFunctionParameterTypeString) { + if !astutils.IsFieldListType(funcType.Params, 1, astutils.IsExprTypeString) { return } - if !astutils.IsFieldListType(funcType.Results, 0, astutils.IsFunctionParameterTypeArrayString) { + if !astutils.IsFieldListType(funcType.Results, 0, astutils.IsExprTypeArrayString) { return } - if !astutils.IsFieldListType(funcType.Results, 1, astutils.IsFunctionParameterTypeArrayError) { + if !astutils.IsFieldListType(funcType.Results, 1, astutils.IsExprTypeArrayError) { return } diff --git a/vendor/github.com/bflad/tfproviderlint/version/version.go b/vendor/github.com/bflad/tfproviderlint/version/version.go index 7a916a9802f..1b0a8292d07 100644 --- a/vendor/github.com/bflad/tfproviderlint/version/version.go +++ b/vendor/github.com/bflad/tfproviderlint/version/version.go @@ -10,7 +10,7 @@ var ( GitCommit string // The main version number that is being run at the moment. - Version = "0.11.0" + Version = "0.12.0" // 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 --git a/vendor/modules.txt b/vendor/modules.txt index 020a7077937..b5dc39a9a50 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -218,7 +218,7 @@ github.com/bflad/tfproviderdocs/check github.com/bflad/tfproviderdocs/check/sidenavigation github.com/bflad/tfproviderdocs/command github.com/bflad/tfproviderdocs/version -# github.com/bflad/tfproviderlint v0.11.0 +# github.com/bflad/tfproviderlint v0.12.0 github.com/bflad/tfproviderlint/cmd/tfproviderlint github.com/bflad/tfproviderlint/helper/analysisutils github.com/bflad/tfproviderlint/helper/astutils @@ -283,6 +283,9 @@ github.com/bflad/tfproviderlint/passes/S031 github.com/bflad/tfproviderlint/passes/S032 github.com/bflad/tfproviderlint/passes/S033 github.com/bflad/tfproviderlint/passes/S034 +github.com/bflad/tfproviderlint/passes/S035 +github.com/bflad/tfproviderlint/passes/S036 +github.com/bflad/tfproviderlint/passes/S037 github.com/bflad/tfproviderlint/passes/V001 github.com/bflad/tfproviderlint/passes/V002 github.com/bflad/tfproviderlint/passes/V003