### Example Custom Filesystem for Testing (MemoryFS) Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/configuration.md Provides an example implementation of a custom filesystem using an in-memory map for testing purposes. ```Go type MemoryFS struct { files map[string][]byte } func (mfs *MemoryFS) Open(name string) (tfconfig.File, error) { // Implementation } func (mfs *MemoryFS) ReadFile(name string) ([]byte, error) { if data, exists := mfs.files[name]; exists { return data, nil } return nil, os.ErrNotExist } func (mfs *MemoryFS) ReadDir(dirname string) ([]os.FileInfo, error) { // Implementation } ``` -------------------------------- ### Custom Filesystem Implementation Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/filesystem-abstraction.md Example of implementing the FS interface for a custom filesystem. Use this with loading functions like LoadModuleFromFilesystem. ```go type MyCustomFS struct { // Custom fields for your filesystem implementation } func (fs *MyCustomFS) Open(name string) (tfconfig.File, error) { // Implementation: open file from custom storage } func (fs *MyCustomFS) ReadFile(name string) ([]byte, error) { // Implementation: read entire file from custom storage } func (fs *MyCustomFS) ReadDir(dirname string) ([]os.FileInfo, error) { // Implementation: list directory contents from custom storage } // Use with loading functions customFS := &MyCustomFS{} module, diags := tfconfig.LoadModuleFromFilesystem(customFS, "modules/vpc") ``` -------------------------------- ### Custom Filesystem Example (In-Memory) Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Provides an example of using an in-memory filesystem for Terraform module loading. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) // CustomFS implements the tfconfig.FS interface for in-memory files. type CustomFS struct { Files map[string][]byte } func (f *CustomFS) Open(name string) (tfconfig.File, error) { content, ok := f.Files[name] if !ok { return nil, fmt.Errorf("file not found: %s", name) } return &customFile{name: name, content: content}, nil } type customFile struct { name string content []byte } func (f *customFile) Read(p []byte) (n int, err error) { return len(f.content), nil } func (f *customFile) Close() error { return nil } func (f *customFile) Name() string { return f.name } func main() { fs := &CustomFS{ Files: map[string][]byte{ "main.tf": []byte("resource \"null_resource\" \"example\" {}"), }, } // Load module using the custom in-memory filesystem module, err := tfconfig.LoadModule("./testdata/simple_module", tfconfig.WithFS(fs)) if err != nil { log.Fatalf("failed to load module with custom FS: %s", err) } fmt.Printf("Module loaded using custom FS: %s\n", module.Path) } ``` -------------------------------- ### SourcePos Type Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Shows how to access SourcePos to get file and line number information for diagnostics. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } for _, diag := range module.Diagnostics { pos := diag.Pos if pos != nil { fmt.Printf("Diagnostic at %s:%d:%d\n", pos.Filename, pos.Line, pos.Column) } } } ``` -------------------------------- ### LoadModule Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Demonstrates basic module loading from a filesystem path. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } fmt.Printf("Module loaded: %s\n", module.Path) } ``` -------------------------------- ### LoadPostInitFromFilesystem Function Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Loads post-init configuration directly from a filesystem path. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { config, err := tfconfig.LoadPostInitFromFilesystem("./testdata/post_init_module") if err != nil { log.Fatalf("failed to load post-init config: %s", err) } fmt.Printf("Post-init config loaded for module: %s\n", config.ModulePath) } ``` -------------------------------- ### Install terraform-config-inspect Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/README.md Install the latest version of the terraform-config-inspect tool using go install. ```bash $ go install github.com/hashicorp/terraform-config-inspect@latest ``` -------------------------------- ### FS Interface Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Demonstrates using the FS interface for abstracting filesystem operations. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) // CustomFS implements the tfconfig.FS interface for in-memory files. type CustomFS struct { Files map[string][]byte } func (f *CustomFS) Open(name string) (tfconfig.File, error) { content, ok := f.Files[name] if !ok { return nil, fmt.Errorf("file not found: %s", name) } return &customFile{name: name, content: content}, nil } type customFile struct { name string content []byte } func (f *customFile) Read(p []byte) (n int, err error) { return len(f.content), nil } func (f *customFile) Close() error { return nil } func (f *customFile) Name() string { return f.name } func main() { fs := &CustomFS{ Files: map[string][]byte{ "main.tf": []byte("resource \"null_resource\" \"example\" {}"), }, } // Wrap the custom filesystem to be used by tfconfig wrappedFS := tfconfig.WrapFS(fs) module, err := tfconfig.LoadModuleFromFilesystem("./testdata/simple_module", tfconfig.WithFS(wrappedFS)) if err != nil { log.Fatalf("failed to load module with custom FS: %s", err) } fmt.Printf("Module loaded using custom FS: %s\n", module.Path) } ``` -------------------------------- ### Post-init Configuration Usage Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Demonstrates using post-init configuration to access resolved provider versions. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { config, err := tfconfig.LoadPostInit("./testdata/post_init_module") if err != nil { log.Fatalf("failed to load post-init config: %s", err) } fmt.Println("Resolved providers:") for _, p := range config.Providers { fmt.Printf("- Name: %s, Version: %s\n", p.Name, p.Version) } } ``` -------------------------------- ### Module Composition Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Analyzes recursive dependencies between modules. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func analyzeModule(path string, depth int) { module, err := tfconfig.LoadModule(path) if err != nil { log.Printf("%sFailed to load module %s: %v", "", path, err) return } indent := "" for i := 0; i < depth; i++ { indent += " " } fmt.Printf("%sModule: %s\n", indent, module.Path) for _, call := range module.ModuleCalls { fmt.Printf("%s Calls: %s (Source: %s)\n", indent, call.Name, call.Source) // Recursively analyze called modules (simplified) // analyzeModule(call.Source, depth+1) } } func main() { analyzeModule("./testdata/recursive_module", 0) } ``` -------------------------------- ### Output Type Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Demonstrates how to access and inspect Output types within a module. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } for _, output := range module.Outputs { fmt.Printf("Output: %s\n", output.Name) fmt.Printf(" Description: %s\n", output.Description) fmt.Printf(" Sensitive: %t\n", output.Sensitive) } } ``` -------------------------------- ### LoadModuleFromFilesystem Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Loads a Terraform module directly from a filesystem path. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModuleFromFilesystem("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } fmt.Printf("Module loaded: %s\n", module.Path) } ``` -------------------------------- ### Iterating Through Components Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/stack-loading.md Example showing how to load a stack and then iterate through its components, printing their names, sources, and definition locations. ```go stack, _ := tfconfig.LoadStack("./infrastructure-stack") // Find all components for name, component := range stack.Components { fmt.Printf("Component: %s\n", name) fmt.Printf(" Source: %s\n", component.Source) fmt.Printf(" Defined at: %s:%d\n", component.Pos.Filename, component.Pos.Line) } ``` -------------------------------- ### Module with Provider Configuration Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/module-calls.md An example of a module call that includes provider configuration. Note that provider configurations are not captured in the ModuleCall struct itself. ```hcl module "vpc_primary" { source = "./modules/vpc" providers = { aws = aws.primary } } ``` -------------------------------- ### Resource Type Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Shows how to retrieve and analyze Resource types from a Terraform module. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } for _, resource := range module.Resources { fmt.Printf("Resource: %s.%s\n", resource.Mode, resource.Name) fmt.Printf(" Type: %s\n", resource.Type) } } ``` -------------------------------- ### LoadStack Example Usage Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/stack-loading.md Example of using `LoadStack` to load a Terraform stack and handle potential errors. It then prints the number of variables, components, and required providers. ```go stack, diags := tfconfig.LoadStack("/path/to/stack") if diags.HasErrors() { fmt.Fprintf(os.Stderr, "errors: %s\n", diags.Error()) os.Exit(1) } fmt.Printf("Stack has %d variables\n", len(stack.Variables)) fmt.Printf("Stack has %d components\n", len(stack.Components)) fmt.Printf("Stack requires providers: %v\n", stack.RequiredProviders) ``` -------------------------------- ### LoadPostInit Function Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Loads configuration after the Terraform init phase, including resolved provider versions. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { config, err := tfconfig.LoadPostInit("./testdata/post_init_module") if err != nil { log.Fatalf("failed to load post-init config: %s", err) } fmt.Printf("Post-init config loaded for module: %s\n", config.ModulePath) } ``` -------------------------------- ### Variable Type Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Illustrates the structure and usage of the Variable type. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } for _, variable := range module.Variables { fmt.Printf("Variable: %s\n", variable.Name) fmt.Printf(" Description: %s\n", variable.Description) fmt.Printf(" Type: %s\n", variable.Type) fmt.Printf(" Default: %v\n", variable.Default) } } ``` -------------------------------- ### Provider Analysis Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Validates provider versions and lists all providers used in a module. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } fmt.Println("Providers:") for _, p := range module.Providers { fmt.Printf("- Name: %s, Source: %s, Version: %s\n", p.Name, p.Source, p.Version) // Add logic here to validate versions against requirements if needed } } ``` -------------------------------- ### Example Module Loading and Access Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/module-struct.md Demonstrates how to load a Terraform module from a directory and access its components like variables, outputs, resources, provider requirements, and module calls. Includes error handling for parsing diagnostics. ```go module, diags := tfconfig.LoadModule("./infrastructure") if diags.HasErrors() { fmt.Printf("Errors during parsing:\n%s\n", diags.Error()) } // Access variables for name, variable := range module.Variables { fmt.Printf("Variable: %s (required: %v)\n", name, variable.Required) } // Access outputs for name, output := range module.Outputs { fmt.Printf("Output: %s\n", name) } // Access resources for key, resource := range module.ManagedResources { fmt.Printf("Resource: %s (type: %s, provider: %s)\n", key, resource.Type, resource.Provider.Name) } // Access provider requirements for name, req := range module.RequiredProviders { fmt.Printf("Provider: %s (source: %s, versions: %v)\n", name, req.Source, req.VersionConstraints) } // Access module calls for name, call := range module.ModuleCalls { fmt.Printf("Module call: %s (source: %s, version: %s)\n", name, call.Source, call.Version) } ``` -------------------------------- ### Multi-Module Analysis Example (Registry) Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Analyzes multiple Terraform modules, including those sourced from a registry. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { // Example: Load a module from the Terraform Registry // Note: This requires network access and Terraform to be configured. registryModule, err := tfconfig.LoadModule("terraform-aws-modules/vpc/aws", "~> 3.0") if err != nil { log.Printf("Could not load module from registry (this may require network access and Terraform configuration): %v\n", err) } if registryModule != nil { fmt.Printf("Loaded registry module: %s\n", registryModule.Path) } // Load a local module for comparison localModule, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load local module: %s", err) } fmt.Printf("Loaded local module: %s\n", localModule.Path) } ``` -------------------------------- ### Diagnostics Methods Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Demonstrates using methods like HasErrors, Error, and Err on the Diagnostics type. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } diagnostics := module.Diagnostics if diagnostics.HasErrors() { fmt.Println("Module has errors:") for _, e := range diagnostics.Error() { fmt.Printf(" - %s\n", e) } } // The Err() method returns a single error if one exists, or nil. if err := diagnostics.Err(); err != nil { fmt.Printf("First error encountered: %s\n", err) } } ``` -------------------------------- ### Resource Analysis Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Finds all AWS resources within a module and groups them by type. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } awsResources := make(map[string][]string) for _, r := range module.Resources { if r.Type == "aws" // This is a simplified check; real-world would involve checking r.Type prefix { awsResources[r.Type] = append(awsResources[r.Type], r.Name) } } fmt.Println("AWS Resources:") for resType, names := range awsResources { fmt.Printf(" %s: %v\n", resType, names) } } ``` -------------------------------- ### NewOsFs Function Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Creates a new filesystem abstraction using the standard operating system filesystem. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { osFS := tfconfig.NewOsFs() // osFS can now be used with WithFS option, e.g.: // module, err := tfconfig.LoadModule("./testdata/simple_module", tfconfig.WithFS(osFS)) fmt.Println("Created a new OS filesystem abstraction.") } ``` -------------------------------- ### Terraform Registry Module Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/module-calls.md An example of a module call referencing a module from the Terraform Registry. This includes specifying a version constraint. ```hcl module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 3.0" } ``` -------------------------------- ### WrapFS Function Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Wraps an existing filesystem implementation (like a custom one) to be compatible with tfconfig. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) // Assume 'myCustomFS' is an implementation of tfconfig.FS var myCustomFS tfconfig.FS func main() { wrappedFS := tfconfig.WrapFS(myCustomFS) // wrappedFS can now be used with WithFS option. fmt.Println("Wrapped a custom filesystem.") } ``` -------------------------------- ### ProviderRef Type Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Illustrates the ProviderRef type, used to reference providers. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } for _, provider := range module.Providers { fmt.Printf("Provider: %s\n", provider.Name) fmt.Printf(" Source: %s\n", provider.Source) fmt.Printf(" Version: %s\n", provider.Version) } } ``` -------------------------------- ### Variable Analysis Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Extracts required variables and their descriptions from a module. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } fmt.Println("Required variables:") for _, v := range module.Variables { if v.Description != "" { fmt.Printf("- %s: %s\n", v.Name, v.Description) } } } ``` -------------------------------- ### LoadStack Function Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Loads a Terraform stack, which is a collection of modules. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { stack, err := tfconfig.LoadStack("./testdata/simple_stack") if err != nil { log.Fatalf("failed to load stack: %s", err) } fmt.Printf("Stack loaded with %d components.\n", len(stack.Components)) } ``` -------------------------------- ### Iterate Through Diagnostics Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/errors.md This example shows how to loop through all diagnostics returned after loading a module. It extracts severity, summary, detail, and location for each diagnostic. ```Go module, diags := tfconfig.LoadModule("./module") for _, diag := range diags { severity := "" switch diag.Severity { case tfconfig.DiagError: severity = "ERROR" case tfconfig.DiagWarning: severity = "WARNING" } fmt.Printf("[%s] %s\n", severity, diag.Summary) if diag.Detail != "" { fmt.Printf(" Detail: %s\n", diag.Detail) } if diag.Pos != nil { fmt.Printf(" Location: %s:%d\n", diag.Pos.Filename, diag.Pos.Line) } } ``` -------------------------------- ### Stack Analysis Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Analyzes a Terraform stack, which is a collection of components (modules). ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { stack, err := tfconfig.LoadStack("./testdata/simple_stack") if err != nil { log.Fatalf("failed to load stack: %s", err) } fmt.Printf("Analyzing stack: %s\n", stack.Path) for _, component := range stack.Components { fmt.Printf(" Component: %s (Type: %s)\n", component.Name, component.Type) // Further analysis of component modules can be done here } } ``` -------------------------------- ### Resource.MapKey() Method Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Retrieves the map key for a given resource instance. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } for _, resource := range module.Resources { mapKey := resource.MapKey() if mapKey != "" { fmt.Printf("Resource %s has map key: %s\n", resource.Name, mapKey) } } } ``` -------------------------------- ### RenderMarkdown Function Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Renders Terraform configuration elements into Markdown format. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } markdown, err := tfconfig.RenderMarkdown(module) if err != nil { log.Fatalf("failed to render markdown: %s", err) } fmt.Println(markdown) } ``` -------------------------------- ### Local Module Reference Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/module-calls.md An example of a local module call in HCL. Local modules are referenced using relative or absolute file paths. ```hcl module "vpc" { source = "./modules/vpc" } ``` -------------------------------- ### Git Repository Module Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/module-calls.md An example of a module call referencing a module from a Git repository. Version constraints are typically not used with Git sources. ```hcl module "vpc" { source = "git::https://github.com/example/modules.git//vpc" } ``` -------------------------------- ### Terraform Cloud/Enterprise Module Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/module-calls.md An example of a module call referencing a module hosted on Terraform Cloud or Enterprise. This includes specifying a version. ```hcl module "vpc" { source = "app.terraform.io/example-corp/vpc/aws" version = "1.2.0" } ``` -------------------------------- ### Error Handling Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Provides comprehensive reporting of errors and warnings found in a module. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/module_with_errors") if err != nil { // LoadModule itself might return an error for critical issues log.Fatalf("failed to load module: %s", err) } diagnostics := module.Diagnostics if diagnostics.HasErrors() { fmt.Println("Errors found:") for _, e := range diagnostics.Error() { fmt.Printf(" - %s\n", e) } } if len(diagnostics) > 0 { fmt.Println("All diagnostics:") for _, d := range diagnostics { fmt.Printf(" - [%s] %s\n", d.Severity, d.Summary) } } } ``` -------------------------------- ### NewModule Constructor Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Creates a new Module object, typically used internally after loading. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { // This is a simplified example; NewModule is usually called by LoadModule. // In a real scenario, you'd have parsed configuration data. module, err := tfconfig.NewModule("./testdata/simple_module", nil) if err != nil { log.Fatalf("failed to create module: %s", err) } fmt.Printf("Module created: %s\n", module.Path) } ``` -------------------------------- ### ModuleCall Type Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Demonstrates how to inspect ModuleCall types, representing calls to other modules. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } for _, call := range module.ModuleCalls { fmt.Printf("Module Call: %s\n", call.Name) fmt.Printf(" Source: %s\n", call.Source) fmt.Printf(" Version: %s\n", call.Version) } } ``` -------------------------------- ### Accessing Stack Information Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/stack-loading.md Example demonstrating how to access and iterate over variables, outputs, components, and required providers within a loaded Terraform stack. ```go stack, diags := tfconfig.LoadStack("./stack") if diags.HasErrors() { fmt.Printf("Errors during parsing:\n%s\n", diags.Error()) } // Access stack variables for name, variable := range stack.Variables { fmt.Printf("Stack Variable: %s (type: %s, required: %v)\n", name, variable.Type, variable.Required) } // Access stack outputs for name, output := range stack.Outputs { fmt.Printf("Stack Output: %s (type: %s)\n", name, output.Type) } // Access components for name, component := range stack.Components { fmt.Printf("Component: %s (source: %s)\n", name, component.Source) } // Access required providers for name, req := range stack.RequiredProviders { fmt.Printf("Provider: %s (source: %s)\n", name, req.Source) } ``` -------------------------------- ### JSON Output Generation Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Demonstrates how to generate JSON output from a Terraform module analysis. ```Go package main import ( "encoding/json" "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } // Marshal the module object to JSON jsonData, err := json.MarshalIndent(module, "", " ") if err != nil { log.Fatalf("failed to marshal module to JSON: %s", err) } fmt.Println(string(jsonData)) } ``` -------------------------------- ### Load Post-Initialization Configuration Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/configuration.md Loads configuration settings after the initial setup, specifying the root directory and the .terraform directory. ```Go import "github.com/hashicorp/terraform-config-inspect/tfconfig" // Load post-init configuration cfg := tfconfig.LoadPostInit(".", ".terraform") ``` -------------------------------- ### NewStack Constructor Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Creates a new Stack object, typically used internally after loading. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { // This is a simplified example; NewStack is usually called by LoadStack. stack, err := tfconfig.NewStack("./testdata/simple_stack", nil) if err != nil { log.Fatalf("failed to create stack: %s", err) } fmt.Printf("Stack created with %d components.\n", len(stack.Components)) } ``` -------------------------------- ### Diagnostic Type Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Illustrates the Diagnostic type, used for reporting errors and warnings. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { module, err := tfconfig.LoadModule("./testdata/simple_module") if err != nil { log.Fatalf("failed to load module: %s", err) } for _, diag := range module.Diagnostics { fmt.Printf("Severity: %s\n", diag.Severity) fmt.Printf(" Summary: %s\n", diag.Summary) fmt.Printf(" Detail: %s\n", diag.Detail) fmt.Printf(" Subject: %s\n", diag.Subject) } } ``` -------------------------------- ### Load Module with OS Filesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/filesystem-abstraction.md Example of loading a Terraform module using the OS filesystem. This utilizes the NewOsFs function internally. ```go osFS := tfconfig.NewOsFs() module, diags := tfconfig.LoadModuleFromFilesystem(osFS, "./modules/vpc") ``` -------------------------------- ### NewModule Constructor Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/module-struct.md Creates a new Module instance with initialized empty maps. Use this to start building a Module object. ```go func NewModule(path string) *Module ``` -------------------------------- ### Get Resolved Provider Versions After Init Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/usage-examples.md Load post-initialization configuration from a working directory to display resolved provider and module versions. This requires the .terraform directory to be present. ```go func showResolvedProviders(workingDir string) { cfg := tfconfig.LoadPostInit(workingDir, filepath.Join(workingDir, ".terraform")) if cfg.Diagnostics.HasErrors() { fmt.Fprintf(os.Stderr, "Error: %s\n", cfg.Diagnostics.Error()) return } fmt.Println("Resolved Providers:") for name, provider := range cfg.Providers { fmt.Printf(" %s: %s@%s\n", name, provider.Source, provider.Version) } if len(cfg.Modules) > 0 { fmt.Println("\nResolved Modules:") for key, module := range cfg.Modules { fmt.Printf(" %s: %s@%s\n", key, module.Source, module.Version) } } } func example() { showResolvedProviders(".") } ``` -------------------------------- ### Wrap Embedded Filesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/filesystem-abstraction.md Example of wrapping an embedded filesystem using WrapFS. This is useful for including Terraform configurations within compiled Go binaries. ```go //go:embed terraform var embeddedFS embed.FS wrappedFS := tfconfig.WrapFS(embeddedFS) module, diags := tfconfig.LoadModuleFromFilesystem(wrappedFS, "modules/vpc") ``` -------------------------------- ### Terraform HCL: Multiple Version Constraints Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/providers.md Example demonstrating how to specify multiple version constraints for a Terraform provider, ensuring compatibility within a range. ```hcl required_providers { aws = { source = "hashicorp/aws" version = ">= 4.0, < 5.0" } } ``` -------------------------------- ### Load Post-Initialization Configuration from Custom Filesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/quick-reference.md Use `LoadPostInitFromFilesystem` to load post-initialization configuration from custom filesystem implementations for both working and data directories. ```go LoadPostInitFromFilesystem(workingFs FS, workingDir string, dataFs FS, dataDir string) *Configuration ``` -------------------------------- ### Load Module with OS Filesystem (Default) Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/configuration.md Demonstrates the default behavior of automatically using the OS filesystem when loading a module. ```Go // Automatic use of OS filesystem module, diags := tfconfig.LoadModule("./module") ``` -------------------------------- ### Loading Post-Init Configuration and Error Checking Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/errors.md Shows how to load configuration after initialization and check for parsing errors and warnings using the Diagnostics field. This is crucial for ensuring the integrity of the loaded configuration. ```go cfg := tfconfig.LoadPostInit(".", ".terraform") // Check for errors if cfg.Diagnostics.HasErrors() { fmt.Fprintf(os.Stderr, "Error loading post-init config:\n") for _, diag := range cfg.Diagnostics { fmt.Fprintf(os.Stderr, " %s\n", diag.Summary) if diag.Detail != "" { fmt.Fprintf(os.Stderr, " %s\n", diag.Detail) } } os.Exit(1) } // Note: Warnings (e.g., "Lock file does not exist") don't prevent success // Check for warnings separately if needed for _, diag := range cfg.Diagnostics { if diag.Severity == tfconfig.DiagWarning { fmt.Printf("Warning: %s\n", diag.Summary) } } ``` -------------------------------- ### IsModuleDirOnFilesystem Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Determines if a directory on the filesystem is a Terraform module. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { isModule, err := tfconfig.IsModuleDirOnFilesystem("./testdata/simple_module") if err != nil { log.Fatalf("failed to check module dir: %s", err) } if isModule { fmt.Println("Directory is a Terraform module.") } else { fmt.Println("Directory is not a Terraform module.") } } ``` -------------------------------- ### Load Post-Init Configuration with Custom Filesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/post-init-config.md Loads the configuration using custom filesystems for the working directory and data directory. This is useful for testing or when working with non-standard file storage. ```go workingFS := MyCustomFilesystem{} dataFS := MyCustomFilesystem{} cfg := tfconfig.LoadPostInitFromFilesystem(workingFS, ".", dataFS, ".terraform") ``` -------------------------------- ### Wrap Standard Library Filesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/filesystem-abstraction.md Demonstrates wrapping a standard library filesystem (os.DirFS) using WrapFS. This allows it to be used with the package's loading functions. ```go import ( "os" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) // Wrap a standard library filesystem stdFS := os.DirFS("./terraform") wrappedFS := tfconfig.WrapFS(stdFS) // Use with loading functions module, diags := tfconfig.LoadModuleFromFilesystem(wrappedFS, "modules/vpc") ``` -------------------------------- ### Load Post-Init Configuration from Filesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/post-init-config.md Loads post-init configuration using custom filesystem implementations for lock files and module manifests. Use this when you need to load configurations from non-standard storage locations. ```go func LoadPostInitFromFilesystem(workingFs FS, workingDir string, dataFs FS, dataDir string) *Configuration ``` ```go cfg := tfconfig.LoadPostInitFromFilesystem( customWFS, "/path/to/root", customDFS, "/path/to/.terraform", ) if cfg.Diagnostics.HasErrors() { for _, diag := range cfg.Diagnostics { fmt.Printf("[%s] %s\n", diag.Severity, diag.Summary) } } ``` -------------------------------- ### Load Terraform Module Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/configuration.md Initializes the library by loading a Terraform module from a specified directory path. ```Go import "github.com/hashicorp/terraform-config-inspect/tfconfig" // Load a module module, diags := tfconfig.LoadModule("./infrastructure") ``` -------------------------------- ### IsModuleDir Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/INDEX.txt Checks if a given directory path points to a valid Terraform module. ```Go package main import ( "fmt" "log" "github.com/hashicorp/terraform-config-inspect/tfconfig" ) func main() { isModule, err := tfconfig.IsModuleDir("./testdata/simple_module") if err != nil { log.Fatalf("failed to check module dir: %s", err) } if isModule { fmt.Println("Directory is a Terraform module.") } else { fmt.Println("Directory is not a Terraform module.") } } ``` -------------------------------- ### Iterating Through Module Required Providers Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/providers.md Demonstrates how to iterate through a module's required providers and print their details, such as source, version constraints, and configuration aliases. ```go module, _ := tfconfig.LoadModule("./module") for name, req := range module.RequiredProviders { fmt.Printf("Provider: %s\n", name) fmt.Printf(" Source: %s\n", req.Source) fmt.Printf(" Version Constraints: %v\n", req.VersionConstraints) fmt.Printf(" Configuration Aliases: ") for _, alias := range req.ConfigurationAliases { fmt.Printf("%s", alias.Name) if alias.Alias != "" { fmt.Printf(".%s ", alias.Alias) } } fmt.Printf("\n") } ``` -------------------------------- ### Load and Inspect All Modules Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/post-init-config.md Loads Terraform configuration after initialization and iterates through all modules, printing their source and version. ```go cfg := tfconfig.LoadPostInit(".", ".terraform") for key, mod := range cfg.Modules { fmt.Printf("Module %s:\n", key) fmt.Printf(" Source: %s\n", mod.Source) if mod.Version != "" { fmt.Printf(" Version: %s\n", mod.Version) } } ``` -------------------------------- ### Load Terraform Stack Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/configuration.md Initializes the library by loading a Terraform stack from a specified directory path. ```Go import "github.com/hashicorp/terraform-config-inspect/tfconfig" // Load a stack stack, diags := tfconfig.LoadStack("./infrastructure-stack") ``` -------------------------------- ### Load Terraform Module from Filesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/README.md Shows how to load a Terraform module from the local operating system's filesystem. An alternative method for loading from a custom filesystem is also provided. ```go // Load from OS filesystem module, _ := tfconfig.LoadModule("./module") // Load from custom filesystem customFS := ... module, _ := tfconfig.LoadModuleFromFilesystem(customFS, "module") ``` -------------------------------- ### Wrap Virtual Filesystem for Testing Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/filesystem-abstraction.md Demonstrates wrapping a virtual filesystem (fstest.MapFS) using WrapFS for testing purposes. This allows for isolated testing of Terraform configuration loading. ```go testFS := fstest.MapFS{ "variables.tf": &fstest.MapFile{Data: []byte(` variable "region" { type = string } `)}, } wrappedFS := tfconfig.WrapFS(testFS) module, diags := tfconfig.LoadModuleFromFilesystem(wrappedFS, ".") ``` -------------------------------- ### Load Post-Init Configuration from Filesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/package-overview.md Loads the resolved providers and modules after 'terraform init' has been run, using standard OS filesystems. This provides access to the configuration as it exists after initialization. ```go func LoadPostInit(workingDir string, dataDir string) *Configuration ``` -------------------------------- ### Terraform Stack Metadata (JSON) Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/README.md Example JSON output from terraform-config-inspect for a Terraform stack, detailing path, variables, outputs, providers, and components. ```json { "path": "path/to/stack", "variables": { "regions": { "name": "regions", "type": "set(string)", "default": null, "required": true, "pos": { "filename": "path/to/stack/variables.tfstack.hcl", "line": 4 } } }, "outputs": { "lambda_urls": { "name": "lambda_urls", "description": "URLs to invoke lambda functions", "pos": { "filename": "path/to/stack/outputs.tfcomponent.hcl", "line": 1 }, "type": "list(string)" } }, "required_providers": { "aws": { "source": "hashicorp/aws" } }, "components": { "s3": { "name": "s3", "source": "./s3", "pos": { "filename": "path/to/stack/components.tfcomponent.hcl", "line": 4 } } } } ``` -------------------------------- ### Terraform Module Metadata (JSON) Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/README.md Example JSON output from terraform-config-inspect for a Terraform module, detailing path, variables, outputs, providers, and resources. ```json { "path": "path/to/module", "variables": { "A": { "name": "A", "default": "A default", "pos": { "filename": "path/to/module/basics.tf", "line": 1 } }, "B": { "name": "B", "description": "The B variable", "pos": { "filename": "path/to/module/basics.tf", "line": 5 } } }, "outputs": { "A": { "name": "A", "pos": { "filename": "path/to/module/basics.tf", "line": 9 } }, "B": { "name": "B", "description": "I am B", "pos": { "filename": "path/to/module/basics.tf", "line": 13 } } }, "required_providers": { "null": [] }, "managed_resources": { "null_resource.A": { "mode": "managed", "type": "null_resource", "name": "A", "provider": { "name": "null" }, "pos": { "filename": "path/to/module/basics.tf", "line": 18 } }, "null_resource.B": { "mode": "managed", "type": "null_resource", "name": "B", "provider": { "name": "null" }, "pos": { "filename": "path/to/module/basics.tf", "line": 19 } } }, "data_resources": {}, "module_calls": {} } ``` -------------------------------- ### Provider Configuration Example Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/module-struct.md Illustrates how a Terraform HCL provider block maps to the ProviderConfig struct, showing the extraction of provider name and alias. ```hcl provider "aws" { alias = "us_west" region = "us-west-2" } ``` -------------------------------- ### Load Post-Initialization Configuration Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/quick-reference.md Use `LoadPostInit` to load the Terraform configuration after initialization, specifying the working directory and data directory. ```go LoadPostInit(workingDir, dataDir string) *Configuration ``` -------------------------------- ### Terraform HCL: Modern Format with Source and Version Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/providers.md Example of a modern Terraform provider requirement specifying both the source address and a version constraint. ```hcl required_providers { aws = { source = "hashicorp/aws" version = ">= 4.0" } } ``` -------------------------------- ### LoadPostInitFromFilesystem Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/post-init-config.md Loads post-init configuration from custom filesystem implementations. This function allows for flexible loading of Terraform configuration files by accepting custom filesystem interfaces for both the working directory and data directory. ```APIDOC ## LoadPostInitFromFilesystem Loads post-init configuration from custom filesystem implementations. ### Description Loads post-init configuration from custom filesystem implementations. This function allows for flexible loading of Terraform configuration files by accepting custom filesystem interfaces for both the working directory and data directory. ### Function Signature ```go func LoadPostInitFromFilesystem(workingFs FS, workingDir string, dataFs FS, dataDir string) *Configuration ``` ### Parameters #### Path Parameters - **workingFs** (FS) - Required - Custom filesystem for reading lock file - **workingDir** (string) - Required - Directory path containing `.terraform.lock.hcl` - **dataFs** (FS) - Required - Custom filesystem for reading modules manifest - **dataDir** (string) - Required - Directory path containing modules manifest ### Returns - `*Configuration`: Configuration with resolved versions from both filesystems ### Example ```go cfg := tfconfig.LoadPostInitFromFilesystem( customWFS, "/path/to/root", customDFS, "/path/to/.terraform", ) if cfg.Diagnostics.HasErrors() { for _, diag := range cfg.Diagnostics { fmt.Printf("[%s] %s\n", diag.Severity, diag.Summary) } } ``` ``` -------------------------------- ### Iterating Through Module Resources Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/resources.md Demonstrates how to load a Terraform module and iterate through its managed and data resources, printing details for each. Verifies the MapKey format for resources. ```go module, _ := tfconfig.LoadModule("./module") // Iterate managed resources for key, resource := range module.ManagedResources { fmt.Printf("Resource: %s\n", key) fmt.Printf(" Type: %s\n", resource.Type) fmt.Printf(" Name: %s\n", resource.Name) fmt.Printf(" Mode: %s\n", resource.Mode.String()) fmt.Printf(" Provider: %s", resource.Provider.Name) if resource.Provider.Alias != "" { fmt.Printf(".%s", resource.Provider.Alias) } fmt.Printf("\n") fmt.Printf(" Location: %s:%d\n", resource.Pos.Filename, resource.Pos.Line) // Verify MapKey format fmt.Printf(" MapKey: %s\n", resource.MapKey()) } // Iterate data resources for key, resource := range module.DataResources { fmt.Printf("Data Source: %s\n", key) fmt.Printf(" Type: %s\n", resource.Type) fmt.Printf(" Provider: %s\n", resource.Provider.Name) } ``` -------------------------------- ### Terraform HCL: Legacy Version Constraint (No Source) Source: https://github.com/hashicorp/terraform-config-inspect/blob/master/_autodocs/api-reference/providers.md Example of a legacy Terraform provider requirement using only a version constraint without specifying a source. ```hcl required_providers { aws = "~> 4.0" } ```