terraform/internal/command/modules.go
Daniel Banck 977a0fb117
Some checks are pending
build / Determine intended Terraform version (push) Waiting to run
build / Determine Go toolchain version (push) Waiting to run
build / Generate release metadata (push) Blocked by required conditions
build / Build for freebsd_386 (push) Blocked by required conditions
build / Build for linux_386 (push) Blocked by required conditions
build / Build for openbsd_386 (push) Blocked by required conditions
build / Build for windows_386 (push) Blocked by required conditions
build / Build for darwin_amd64 (push) Blocked by required conditions
build / Build for freebsd_amd64 (push) Blocked by required conditions
build / Build for linux_amd64 (push) Blocked by required conditions
build / Build for openbsd_amd64 (push) Blocked by required conditions
build / Build for solaris_amd64 (push) Blocked by required conditions
build / Build for windows_amd64 (push) Blocked by required conditions
build / Build for freebsd_arm (push) Blocked by required conditions
build / Build for linux_arm (push) Blocked by required conditions
build / Build for darwin_arm64 (push) Blocked by required conditions
build / Build for linux_arm64 (push) Blocked by required conditions
build / Build for windows_arm64 (push) Blocked by required conditions
build / Build Docker image for linux_386 (push) Blocked by required conditions
build / Build Docker image for linux_amd64 (push) Blocked by required conditions
build / Build Docker image for linux_arm (push) Blocked by required conditions
build / Build Docker image for linux_arm64 (push) Blocked by required conditions
build / Build e2etest for linux_386 (push) Blocked by required conditions
build / Build e2etest for windows_386 (push) Blocked by required conditions
build / Build e2etest for darwin_amd64 (push) Blocked by required conditions
build / Build e2etest for linux_amd64 (push) Blocked by required conditions
build / Build e2etest for windows_amd64 (push) Blocked by required conditions
build / Build e2etest for linux_arm (push) Blocked by required conditions
build / Build e2etest for darwin_arm64 (push) Blocked by required conditions
build / Build e2etest for linux_arm64 (push) Blocked by required conditions
build / Run e2e test for linux_386 (push) Blocked by required conditions
build / Run e2e test for windows_386 (push) Blocked by required conditions
build / Run e2e test for darwin_amd64 (push) Blocked by required conditions
build / Run e2e test for linux_amd64 (push) Blocked by required conditions
build / Run e2e test for windows_amd64 (push) Blocked by required conditions
build / Run e2e test for linux_arm (push) Blocked by required conditions
build / Run e2e test for linux_arm64 (push) Blocked by required conditions
build / Run terraform-exec test for linux amd64 (push) Blocked by required conditions
Quick Checks / Unit Tests (push) Waiting to run
Quick Checks / Race Tests (push) Waiting to run
Quick Checks / End-to-end Tests (push) Waiting to run
Quick Checks / Code Consistency Checks (push) Waiting to run
Potentially fetch backend variables for most commands
* modules
* providers
* providers lock
* providers mirror
* validate
* state mv
* state pull
* state push
* state replace provider
* state rm
* taint
* get
2026-03-17 16:41:28 +01:00

164 lines
4.5 KiB
Go

// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
package command
import (
"errors"
"fmt"
"github.com/hashicorp/terraform/internal/command/arguments"
"github.com/hashicorp/terraform/internal/command/views"
"github.com/hashicorp/terraform/internal/modsdir"
"github.com/hashicorp/terraform/internal/moduleref"
"github.com/hashicorp/terraform/internal/terraform"
"github.com/hashicorp/terraform/internal/tfdiags"
)
// ModulesCommand is a Command implementation that prints out information
// about the modules declared by the current configuration.
type ModulesCommand struct {
Meta
viewType arguments.ViewType
}
func (c *ModulesCommand) Help() string {
return modulesCommandHelp
}
func (c *ModulesCommand) Synopsis() string {
return "Show all declared modules in a working directory"
}
func (c *ModulesCommand) Run(rawArgs []string) int {
// Parse global view arguments
rawArgs = c.Meta.process(rawArgs)
common, rawArgs := arguments.ParseView(rawArgs)
c.View.Configure(common)
// Parse command specific flags
args, diags := arguments.ParseModules(rawArgs)
if diags.HasErrors() {
c.View.Diagnostics(diags)
c.View.HelpPrompt("modules")
return 1
}
c.viewType = args.ViewType
// Set up the command's view
view := views.NewModules(c.viewType, c.View)
loader, err := c.initConfigLoader()
if err != nil {
diags = diags.Append(err)
view.Diagnostics(diags)
return 1
}
var varDiags tfdiags.Diagnostics
c.VariableValues, varDiags = args.Vars.CollectValues(func(filename string, src []byte) {
loader.Parser().ForceFileSource(filename, src)
})
diags = diags.Append(varDiags)
if diags.HasErrors() {
view.Diagnostics(diags)
return 1
}
rootModPath, err := ModulePath([]string{})
if err != nil {
diags = diags.Append(err)
view.Diagnostics(diags)
return 1
}
// Read the root module path so we can then traverse the tree
rootModEarly, earlyConfDiags := c.loadSingleModule(rootModPath)
if rootModEarly == nil {
diags = diags.Append(errors.New("root module not found. Please run terraform init"), earlyConfDiags)
view.Diagnostics(diags)
return 1
}
diags = diags.Append(c.resolveConstVariables(rootModPath, args.ViewType))
if diags.HasErrors() {
view.Diagnostics(diags)
return 1
}
config, confDiags := c.loadConfig(rootModPath)
// Here we check if there are any uninstalled dependencies
versionDiags := terraform.CheckCoreVersionRequirements(config)
if versionDiags.HasErrors() {
view.Diagnostics(versionDiags)
return 1
}
diags = diags.Append(earlyConfDiags)
if earlyConfDiags.HasErrors() {
view.Diagnostics(diags)
return 1
}
diags = diags.Append(confDiags)
if confDiags.HasErrors() {
view.Diagnostics(diags)
return 1
}
// Fetch the module manifest
internalManifest, diags := c.internalManifest()
if diags.HasErrors() {
view.Diagnostics(diags)
return 1
}
// Create a module reference resolver
resolver := moduleref.NewResolver(internalManifest)
// Crawl the Terraform config and find entries with references
manifestWithRef := resolver.Resolve(config)
// Render the new manifest with references
return view.Display(*manifestWithRef)
}
// internalManifest will use the configuration loader to refresh and load the
// internal manifest.
func (c *ModulesCommand) internalManifest() (modsdir.Manifest, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
loader, err := c.initConfigLoader()
if err != nil {
diags = diags.Append(fmt.Errorf("Failed to initialize config loader: %w", err))
return nil, diags
}
if err = loader.RefreshModules(); err != nil {
diags = diags.Append(fmt.Errorf("Failed to refresh module manifest: %w", err))
return nil, diags
}
return loader.ModuleManifest(), diags
}
const modulesCommandHelp = `
Usage: terraform [global options] modules [options]
Prints out a list of all declared Terraform modules and their resolved versions
in a Terraform working directory.
Options:
-json If specified, output declared Terraform modules and
their resolved versions in a machine-readable format.
-var 'foo=bar' Set a value for one of the input variables in the root
module of the configuration. Use this option more than
once to set more than one variable.
-var-file=filename Load variable values from the given file, in addition
to the default files terraform.tfvars and *.auto.tfvars.
Use this option more than once to include more than one
variables file.
`