From 54b67a99eba0439fb010d11603a2347d16e2a302 Mon Sep 17 00:00:00 2001 From: bgpat Date: Thu, 26 Sep 2024 09:22:31 +0900 Subject: [PATCH] Support provider-defined functions --- rules/terraform_required_providers_test.go | 24 +++++++++++++++++++ ...erraform_unused_required_providers_test.go | 16 +++++++++++++ terraform/runner.go | 23 ++++++++++++++++-- terraform/runner_test.go | 10 ++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/rules/terraform_required_providers_test.go b/rules/terraform_required_providers_test.go index 388ef88..e49db60 100644 --- a/rules/terraform_required_providers_test.go +++ b/rules/terraform_required_providers_test.go @@ -546,6 +546,30 @@ resource "google_compute_instance" "foo" { }, }, }, + { + Name: "provider-defined function", + Content: ` +output "foo" { + value = provider::time::rfc3339_parse("2023-07-25T23:43:16Z") +}`, + Expected: helper.Issues{ + { + Rule: NewTerraformRequiredProvidersRule(), + Message: "Missing version constraint for provider \"time\" in `required_providers`", + Range: hcl.Range{ + Filename: "module.tf", + Start: hcl.Pos{ + Line: 3, + Column: 10, + }, + End: hcl.Pos{ + Line: 3, + Column: 63, + }, + }, + }, + }, + }, } rule := NewTerraformRequiredProvidersRule() diff --git a/rules/terraform_unused_required_providers_test.go b/rules/terraform_unused_required_providers_test.go index 693fe14..0ac06a7 100644 --- a/rules/terraform_unused_required_providers_test.go +++ b/rules/terraform_unused_required_providers_test.go @@ -244,6 +244,22 @@ func Test_TerraformUnusedRequiredProvidersRule(t *testing.T) { `, Expected: helper.Issues{}, }, + { + Name: "used - provider-defined function", + Content: ` + terraform { + required_providers { + time = { + source = "hashicorp/time" + } + } + } + output "foo" { + value = provider::time::rfc3339_parse("2023-07-25T23:43:16Z") + } + `, + Expected: helper.Issues{}, + }, } rule := NewTerraformUnusedRequiredProvidersRule() diff --git a/terraform/runner.go b/terraform/runner.go index 020fe75..f51d1f0 100644 --- a/terraform/runner.go +++ b/terraform/runner.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/terraform-linters/tflint-plugin-sdk/hclext" "github.com/terraform-linters/tflint-plugin-sdk/tflint" ) @@ -104,7 +105,7 @@ func (r *Runner) GetLocals() (map[string]*Local, hcl.Diagnostics) { return locals, diags } -// GetProviderRefs returns all references to providers in resources, data, provider declarations, and module calls. +// GetProviderRefs returns all references to providers in resources, data, provider declarations, module calls, and provider-defined functinos. func (r *Runner) GetProviderRefs() (map[string]*ProviderRef, hcl.Diagnostics) { providerRefs := map[string]*ProviderRef{} @@ -241,5 +242,23 @@ func (r *Runner) GetProviderRefs() (map[string]*ProviderRef, hcl.Diagnostics) { } } - return providerRefs, nil + walkDiags := r.WalkExpressions(tflint.ExprWalkFunc(func(expr hcl.Expression) hcl.Diagnostics { + if fce, ok := expr.(*hclsyntax.FunctionCallExpr); ok { + parts := strings.Split(fce.Name, "::") + if len(parts) < 2 || parts[0] != "provider" || parts[1] == "" { + return nil + } + providerRefs[parts[1]] = &ProviderRef{ + Name: parts[1], + DefRange: expr.Range(), + } + } + return nil + })) + diags = diags.Extend(walkDiags) + if walkDiags.HasErrors() { + return providerRefs, diags + } + + return providerRefs, diags } diff --git a/terraform/runner_test.go b/terraform/runner_test.go index 2b5293b..5338bdd 100644 --- a/terraform/runner_test.go +++ b/terraform/runner_test.go @@ -260,6 +260,16 @@ check "my_check" { "aws": {Name: "aws", DefRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 3}, End: hcl.Pos{Line: 3, Column: 24}}}, }, }, + { + name: "provider-defined function", + content: ` +output "foo" { + value = provider::time::rfc3339_parse("2023-07-25T23:43:16Z") +}`, + want: map[string]*ProviderRef{ + "time": {Name: "time", DefRange: hcl.Range{Filename: "main.tf", Start: hcl.Pos{Line: 3, Column: 11}, End: hcl.Pos{Line: 3, Column: 64}}}, + }, + }, } for _, test := range tests {