Merge pull request #651 from kampka/ignore-input-vars

Ignore inputs with terraform-docs-ignore comment
This commit is contained in:
Khosrow Moossavi
2024-05-30 12:39:44 -04:00
committed by GitHub
19 changed files with 273 additions and 13 deletions

View File

@@ -4,7 +4,7 @@ description: "How to generate terraform.tfvars file with terraform-docs"
menu:
docs:
parent: "how-to"
weight: 207
weight: 208
toc: false
---

View File

@@ -4,7 +4,7 @@ description: "How to use terraform-docs with GitHub Actions"
menu:
docs:
parent: "how-to"
weight: 208
weight: 209
toc: false
---

View File

@@ -0,0 +1,74 @@
---
title: "Ignore Resources to be Generated"
description: "How to ignore resources from generated output"
menu:
docs:
parent: "how-to"
weight: 204
toc: false
---
Since `v0.18.0`
Any type of resources can be ignored from the generated output by prepending them
with a comment `terraform-docs-ignore`. Supported type of Terraform resources to
get ignored are:
- `resource`
- `data`
- `module`
- `variable`
- `output`
{{< alert type="info" >}}
If a `resource` or `data` is ignored, their corresponding discovered provider
will also get ignored from "Providers" section.
{{< /alert>}}
Take the following example:
```hcl
##################################################################
# All of the following will be ignored from the generated output #
##################################################################
# terraform-docs-ignore
resource "foo_resource" "foo" {}
# This resource is going to get ignored from generated
# output by using the following known comment.
#
# terraform-docs-ignore
#
# The ignore keyword also doesn't have to be the first,
# last, or the only thing in a leading comment
resource "bar_resource" "bar" {}
# terraform-docs-ignore
data "foo_data_resource" "foo" {}
# terraform-docs-ignore
data "bar_data_resource" "bar" {}
// terraform-docs-ignore
module "foo" {
source = "foo"
version = "x.x.x"
}
# terraform-docs-ignore
variable "foo" {
default = "foo"
}
// terraform-docs-ignore
output "foo" {
value = "foo"
}
```
{{< alert type="info" >}}
The ignore keyword (i.e. `terraform-docs-ignore`) doesn't have to be the first,
last, or only thing in a leading comment. As long as the keyword is present in
a comment, the following resource will get ignored.
{{< /alert>}}

View File

@@ -4,7 +4,7 @@ description: "How to include example in terraform-docs generated output"
menu:
docs:
parent: "how-to"
weight: 205
weight: 206
toc: false
---

View File

@@ -4,7 +4,7 @@ description: "How to insert generated terraform-docs output to file"
menu:
docs:
parent: "how-to"
weight: 204
weight: 205
toc: false
---

View File

@@ -4,7 +4,7 @@ description: "How to use pre-commit hooks with terraform-docs"
menu:
docs:
parent: "how-to"
weight: 209
weight: 210
toc: false
---

View File

@@ -4,7 +4,7 @@ description: "How to generate submodules documentation recursively with terrafor
menu:
docs:
parent: "how-to"
weight: 206
weight: 207
toc: false
---

View File

@@ -63,8 +63,20 @@ data "aws_caller_identity" "ident" {
provider = "aws.ident"
}
# terraform-docs-ignore
data "aws_caller_identity" "ignored" {
provider = "aws"
}
resource "null_resource" "foo" {}
# This resource is going to get ignored from generated
# output by using the following known comment.
# terraform-docs-ignore
# And the ignore keyword also doesn't have to be the first,
# last, or only thing in a leading comment
resource "null_resource" "ignored" {}
module "bar" {
source = "baz"
version = "4.5.6"
@@ -84,3 +96,9 @@ module "baz" {
module "foobar" {
source = "git@github.com:module/path?ref=v7.8.9"
}
// terraform-docs-ignore
module "ignored" {
source = "foobaz"
version = "7.8.9"
}

View File

@@ -17,3 +17,8 @@ output "output-0.12" {
value = join(",", var.list-3)
description = "terraform 0.12 only"
}
// terraform-docs-ignore
output "ignored" {
value = "ignored"
}

View File

@@ -14,6 +14,11 @@ variable "bool-1" {
default = true
}
# terraform-docs-ignore
variable "ignored" {
default = ""
}
variable "string-3" {
default = ""
}

2
go.mod
View File

@@ -17,6 +17,7 @@ require (
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
github.com/terraform-docs/terraform-config-inspect v0.0.0-20210728164355-9c1f178932fa
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d
gopkg.in/yaml.v3 v3.0.1
honnef.co/go/tools v0.3.2
mvdan.cc/xurls/v2 v2.5.0
@@ -58,7 +59,6 @@ require (
github.com/zclconf/go-cty v1.14.4 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/exp v0.0.0-20240525044651-4c93da0ed11d // indirect
golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.25.0 // indirect

View File

@@ -187,10 +187,17 @@ func loadInputs(tfmodule *tfconfig.Module, config *print.Config) ([]*Input, []*I
var optional = make([]*Input, 0, len(tfmodule.Variables))
for _, input := range tfmodule.Variables {
comments := loadComments(input.Pos.Filename, input.Pos.Line)
// skip over inputs that are marked as being ignored
if strings.Contains(comments, "terraform-docs-ignore") {
continue
}
// convert CRLF to LF early on (https://github.com/terraform-docs/terraform-docs/issues/305)
inputDescription := strings.ReplaceAll(input.Description, "\r\n", "\n")
if inputDescription == "" && config.Settings.ReadComments {
inputDescription = loadComments(input.Pos.Filename, input.Pos.Line)
inputDescription = comments
}
i := &Input{
@@ -245,13 +252,20 @@ func loadModulecalls(tfmodule *tfconfig.Module, config *print.Config) []*ModuleC
var source, version string
for _, m := range tfmodule.ModuleCalls {
source, version = formatSource(m.Source, m.Version)
comments := loadComments(m.Pos.Filename, m.Pos.Line)
// skip over modules that are marked as being ignored
if strings.Contains(comments, "terraform-docs-ignore") {
continue
}
description := ""
if config.Settings.ReadComments {
description = loadComments(m.Pos.Filename, m.Pos.Line)
description = comments
}
source, version = formatSource(m.Source, m.Version)
modules = append(modules, &ModuleCall{
Name: m.Name,
Source: source,
@@ -277,10 +291,17 @@ func loadOutputs(tfmodule *tfconfig.Module, config *print.Config) ([]*Output, er
}
}
for _, o := range tfmodule.Outputs {
comments := loadComments(o.Pos.Filename, o.Pos.Line)
// skip over outputs that are marked as being ignored
if strings.Contains(comments, "terraform-docs-ignore") {
continue
}
// convert CRLF to LF early on (https://github.com/terraform-docs/terraform-docs/issues/584)
description := strings.ReplaceAll(o.Description, "\r\n", "\n")
if description == "" && config.Settings.ReadComments {
description = loadComments(o.Pos.Filename, o.Pos.Line)
description = comments
}
output := &Output{
@@ -330,7 +351,11 @@ func loadOutputValues(config *print.Config) (map[string]*output, error) {
return terraformOutputs, err
}
func loadProviders(tfmodule *tfconfig.Module, config *print.Config) []*Provider {
func loadProviders(tfmodule *tfconfig.Module, config *print.Config) []*Provider { //nolint:gocyclo
// NOTE(khos2ow): this function is over our cyclomatic complexity goal.
// Be wary when adding branches, and look for functionality that could
// be reasonably moved into an injected dependency.
type provider struct {
Name string `hcl:"name,label"`
Version string `hcl:"version"`
@@ -360,6 +385,13 @@ func loadProviders(tfmodule *tfconfig.Module, config *print.Config) []*Provider
for _, resource := range resources {
for _, r := range resource {
comments := loadComments(r.Pos.Filename, r.Pos.Line)
// skip over resources that are marked as being ignored
if strings.Contains(comments, "terraform-docs-ignore") {
continue
}
var version = ""
if l, ok := lock[r.Provider.Name]; ok {
version = l.Version
@@ -368,6 +400,10 @@ func loadProviders(tfmodule *tfconfig.Module, config *print.Config) []*Provider
}
key := fmt.Sprintf("%s.%s", r.Provider.Name, r.Provider.Alias)
if _, ok := discovered[key]; ok {
continue
}
discovered[key] = &Provider{
Name: r.Provider.Name,
Alias: types.String(r.Provider.Alias),
@@ -384,6 +420,7 @@ func loadProviders(tfmodule *tfconfig.Module, config *print.Config) []*Provider
for _, provider := range discovered {
providers = append(providers, provider)
}
return providers
}
@@ -420,6 +457,13 @@ func loadResources(tfmodule *tfconfig.Module, config *print.Config) []*Resource
for _, resource := range allResources {
for _, r := range resource {
comments := loadComments(r.Pos.Filename, r.Pos.Line)
// skip over resources that are marked as being ignored
if strings.Contains(comments, "terraform-docs-ignore") {
continue
}
var version string
if rv, ok := tfmodule.RequiredProviders[r.Provider.Name]; ok {
version = resourceVersion(rv.VersionConstraints)
@@ -437,7 +481,7 @@ func loadResources(tfmodule *tfconfig.Module, config *print.Config) []*Resource
description := ""
if config.Settings.ReadComments {
description = loadComments(r.Pos.Filename, r.Pos.Line)
description = comments
}
discovered[key] = &Resource{

View File

@@ -11,12 +11,14 @@ the root directory of this source tree.
package terraform
import (
"fmt"
"os"
"path/filepath"
"sort"
"testing"
"github.com/stretchr/testify/assert"
"golang.org/x/exp/slices"
"github.com/terraform-docs/terraform-docs/print"
)
@@ -38,6 +40,7 @@ func TestLoadModuleWithOptions(t *testing.T) {
assert.Equal(true, module.HasModuleCalls())
assert.Equal(true, module.HasProviders())
assert.Equal(true, module.HasRequirements())
assert.Equal(true, module.HasResources())
config.Sections.Header = false
config.Sections.Footer = true
@@ -774,6 +777,87 @@ func TestLoadProviders(t *testing.T) {
}
}
func TestLoadRequirements(t *testing.T) {
type expected struct {
requirements []string
}
tests := []struct {
name string
path string
expected expected
}{
{
name: "load module requirements from path",
path: "full-example",
expected: expected{
requirements: []string{"terraform >= 0.12", "aws >= 2.15.0"},
},
},
{
name: "load module requirements from path",
path: "no-requirements",
expected: expected{
requirements: []string{},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
module, _ := loadModule(filepath.Join("testdata", tt.path))
requirements := loadRequirements(module)
assert.Equal(len(tt.expected.requirements), len(requirements))
for i, r := range tt.expected.requirements {
assert.Equal(r, fmt.Sprintf("%s %s", requirements[i].Name, requirements[i].Version))
}
})
}
}
func TestLoadResources(t *testing.T) {
type expected struct {
resources []string
}
tests := []struct {
name string
path string
expected expected
}{
{
name: "load module resources from path",
path: "full-example",
expected: expected{
resources: []string{"tls_private_key.baz", "aws_caller_identity.current", "null_resource.foo"},
},
},
{
name: "load module resources from path",
path: "no-resources",
expected: expected{
resources: []string{},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert := assert.New(t)
config := print.NewConfig()
module, _ := loadModule(filepath.Join("testdata", tt.path))
resources := loadResources(module, config)
assert.Equal(len(tt.expected.resources), len(resources))
for _, r := range resources {
assert.True(slices.Contains(tt.expected.resources, fmt.Sprintf("%s_%s.%s", r.ProviderName, r.Type, r.Name)))
}
})
}
}
func TestLoadComments(t *testing.T) {
tests := []struct {
name string

View File

@@ -21,8 +21,16 @@ data "aws_caller_identity" "current" {
provider = "aws"
}
# terraform-docs-ignore
data "aws_caller_identity" "ignored" {
provider = "aws"
}
resource "null_resource" "foo" {}
# terraform-docs-ignore
resource "null_resource" "ignored" {}
module "foo" {
source = "bar"
version = "1.2.3"
@@ -35,3 +43,9 @@ module "foobar" {
locals {
arn = provider::aws::arn_parse("arn:aws:iam::444455556666:role/example")
}
// terraform-docs-ignore
module "ignored" {
source = "baz"
version = "1.2.3"
}

View File

@@ -17,3 +17,8 @@ output "B" {
output "D" {
value = null
}
# terraform-docs-ignore
output "ignored" {
value = "e"
}

View File

@@ -28,3 +28,9 @@ variable "G" {
description = "G description"
default = null
}
# terraform-docs-ignore
variable "ignored" {
description = "H description"
default = null
}

View File

View File

View File

@@ -7,3 +7,8 @@ variable "B" {
output "B" {
value = "b"
}
// terraform-docs-ignore
output "ignored" {
value = "c"
}