Skip to content

Commit 57cf3db

Browse files
committed
Extract provider version from .terraform.lock.hcl
If .terraform.lock.hcl exists in module path, try to extract the exact provider version being used as opposed to provided constraints. Signed-off-by: Khosrow Moossavi <khos2ow@gmail.com>
1 parent a1bd63b commit 57cf3db

File tree

7 files changed

+174
-4
lines changed

7 files changed

+174
-4
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/BurntSushi/toml v0.3.1
77
github.com/hashicorp/go-plugin v1.4.0
88
github.com/hashicorp/go-version v1.3.0
9+
github.com/hashicorp/hcl/v2 v2.0.0
910
github.com/iancoleman/orderedmap v0.2.0
1011
github.com/imdario/mergo v0.3.11
1112
github.com/mitchellh/go-homedir v1.1.0

internal/terraform/module.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"strconv"
2424
"strings"
2525

26+
"github.com/hashicorp/hcl/v2/hclsimple"
27+
2628
terraformsdk "github.com/terraform-docs/plugin-sdk/terraform"
2729
"github.com/terraform-docs/terraform-config-inspect/tfconfig"
2830
"github.com/terraform-docs/terraform-docs/internal/reader"
@@ -152,7 +154,7 @@ func loadModuleItems(tfmodule *tfconfig.Module, options *Options) (*Module, erro
152154
if err != nil {
153155
return nil, err
154156
}
155-
providers := loadProviders(tfmodule)
157+
providers := loadProviders(tfmodule, options)
156158
requirements := loadRequirements(tfmodule)
157159
resources := loadResources(tfmodule)
158160

@@ -398,14 +400,37 @@ func loadOutputValues(options *Options) (map[string]*output, error) {
398400
return terraformOutputs, err
399401
}
400402

401-
func loadProviders(tfmodule *tfconfig.Module) []*Provider {
403+
func loadProviders(tfmodule *tfconfig.Module, options *Options) []*Provider {
404+
type provider struct {
405+
Name string `hcl:"name,label"`
406+
Version string `hcl:"version"`
407+
Constraints *string `hcl:"constraints"`
408+
Hashes []string `hcl:"hashes"`
409+
}
410+
type lockfile struct {
411+
Provider []provider `hcl:"provider,block"`
412+
}
413+
lock := make(map[string]provider)
414+
var lf lockfile
415+
416+
filename := filepath.Join(options.Path, ".terraform.lock.hcl")
417+
if err := hclsimple.DecodeFile(filename, nil, &lf); err == nil {
418+
for i := range lf.Provider {
419+
segments := strings.Split(lf.Provider[i].Name, "/")
420+
name := segments[len(segments)-1]
421+
lock[name] = lf.Provider[i]
422+
}
423+
}
424+
402425
resources := []map[string]*tfconfig.Resource{tfmodule.ManagedResources, tfmodule.DataResources}
403426
discovered := make(map[string]*Provider)
404427

405428
for _, resource := range resources {
406429
for _, r := range resource {
407430
var version = ""
408-
if rv, ok := tfmodule.RequiredProviders[r.Provider.Name]; ok && len(rv.VersionConstraints) > 0 {
431+
if l, ok := lock[r.Provider.Name]; ok {
432+
version = l.Version
433+
} else if rv, ok := tfmodule.RequiredProviders[r.Provider.Name]; ok && len(rv.VersionConstraints) > 0 {
409434
version = strings.Join(rv.VersionConstraints, " ")
410435
}
411436

internal/terraform/module_test.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,13 @@ func TestLoadProviders(t *testing.T) {
679679
providers: 3,
680680
},
681681
},
682+
{
683+
name: "load module providers from path",
684+
path: "with-lock-file",
685+
expected: expected{
686+
providers: 3,
687+
},
688+
},
682689
{
683690
name: "load module providers from path",
684691
path: "no-providers",
@@ -690,8 +697,11 @@ func TestLoadProviders(t *testing.T) {
690697
for _, tt := range tests {
691698
t.Run(tt.name, func(t *testing.T) {
692699
assert := assert.New(t)
700+
options, _ := NewOptions().With(&Options{
701+
Path: tt.path,
702+
})
693703
module, _ := loadModule(filepath.Join("testdata", tt.path))
694-
providers := loadProviders(module)
704+
providers := loadProviders(module, options)
695705

696706
assert.Equal(tt.expected.providers, len(providers))
697707
})

internal/terraform/testdata/with-lock-file/.terraform.lock.hcl

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Example of 'foo_bar' module in `foo_bar.tf`.
3+
*
4+
* - list item 1
5+
* - list item 2
6+
*
7+
* Even inline **formatting** in _here_ is possible.
8+
* and some [link](https://domain.com/)
9+
*/
10+
11+
terraform {
12+
required_version = ">= 0.12"
13+
required_providers {
14+
aws = ">= 2.15.0"
15+
}
16+
}
17+
18+
resource "tls_private_key" "baz" {}
19+
20+
data "aws_caller_identity" "current" {
21+
provider = "aws"
22+
}
23+
24+
resource "null_resource" "foo" {}
25+
26+
module "foo" {
27+
source = "bar"
28+
version = "1.2.3"
29+
}
30+
31+
module "foobar" {
32+
source = "git@github.com:module/path?ref=v7.8.9"
33+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
output C {
2+
description = "It's unquoted output."
3+
value = "c"
4+
}
5+
6+
output "A" {
7+
description = "A description"
8+
value = "a"
9+
}
10+
11+
// B description
12+
output "B" {
13+
value = "b"
14+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// D description
2+
variable "D" {
3+
default = "d"
4+
}
5+
6+
variable "B" {
7+
default = "b"
8+
}
9+
10+
variable "E" {
11+
default = ""
12+
}
13+
14+
# A Description
15+
# in multiple lines
16+
variable A {}
17+
18+
variable "C" {
19+
description = "C description"
20+
default = "c"
21+
}
22+
23+
variable "F" {
24+
description = "F description"
25+
}
26+
27+
variable "G" {
28+
description = "G description"
29+
default = null
30+
}

0 commit comments

Comments
 (0)