Documentation ¶
Overview ¶
Package tfconfig is a helper library that does careful, shallow parsing of Terraform modules to provide access to high-level metadata while remaining broadly compatible with configurations targeting various different Terraform versions.
This packge focuses on describing top-level objects only, and in particular does not attempt any sort of processing that would require access to plugins. Currently it allows callers to extract high-level information about variables, outputs, resource blocks, provider dependencies, and Terraform Core dependencies.
This package only works at the level of single modules. A full configuration is a tree of potentially several modules, some of which may be references to remote packages. There are some basic helpers for traversing calls to modules at relative local paths, however.
This package employs a "best effort" parsing strategy, producing as complete a result as possible even though the input may not be entirely valid. The intended use-case is high-level analysis and indexing of externally-facing module characteristics, as opposed to validating or even applying the module.
Index ¶
- Constants
- func IsModuleDir(dir string) bool
- func IsModuleDirOnFilesystem(fs FS, dir string) bool
- func LoadModule(dir string, resolvedModuleRefs *ResolvedModulesSchema) (*Module, Diagnostics)
- func LoadModuleFromFile(file *hcl.File, mod *Module, resolvedModuleRefs *ResolvedModulesSchema) hcl.Diagnostics
- func LoadModuleFromFilesystem(fs FS, dir string, resolvedModuleRefs *ResolvedModulesSchema) (*Module, Diagnostics)
- func LoadModulesFromResolvedSchema(schemaFilePath string, filters ...ResolvedModuleSchemaFilter) ([]*Module, []Diagnostics, error)
- func RenderMarkdown(w io.Writer, module *Module) error
- type AttributeReference
- type DiagSeverity
- type Diagnostic
- type Diagnostics
- type FS
- type File
- type Local
- type Metadata
- type Module
- type ModuleCall
- type ModuleReference
- type Output
- type ParserContext
- type ProviderConfig
- type ProviderRef
- type ProviderRequirement
- type RelativeAttributeReference
- type ResolvedModuleSchemaFilter
- type ResolvedModulesSchema
- type Resource
- type ResourceAttributeReference
- func (r ResourceAttributeReference) Attribute() string
- func (r *ResourceAttributeReference) CopyValues(other ResourceAttributeReference) *ResourceAttributeReference
- func (r ResourceAttributeReference) MakeRelative(relativePath []string) RelativeAttributeReference
- func (r ResourceAttributeReference) Name() string
- func (r ResourceAttributeReference) Path() string
- func (r ResourceAttributeReference) PathSegments() []string
- func (r ResourceAttributeReference) Pos() (string, int)
- func (r ResourceAttributeReference) Root() string
- func (r ResourceAttributeReference) RootExpression() hcl.Expression
- func (r ResourceAttributeReference) String() string
- func (r ResourceAttributeReference) Type() string
- type ResourceMode
- type SourcePos
- type Variable
Constants ¶
const AttributePathSeparator = "."
Variables ¶
This section is empty.
Functions ¶
func IsModuleDir ¶
IsModuleDir checks if the given path contains terraform configuration files. This allows the caller to decide how to handle directories that do not have tf files.
func IsModuleDirOnFilesystem ¶
IsModuleDirOnFilesystem checks if the given path in the given FS contains Terraform configuration files. This allows the caller to decide how to handle directories that do not have tf files.
func LoadModule ¶
func LoadModule(dir string, resolvedModuleRefs *ResolvedModulesSchema) (*Module, Diagnostics)
LoadModule reads the directory at the given path and attempts to interpret it as a Terraform module.
func LoadModuleFromFile ¶
func LoadModuleFromFile(file *hcl.File, mod *Module, resolvedModuleRefs *ResolvedModulesSchema) hcl.Diagnostics
LoadModuleFromFile reads given file, interprets it and stores in given Module This is useful for any caller which does tokenization/parsing on its own e.g. because it will reuse these parsed files later for more detailed interpretation.
func LoadModuleFromFilesystem ¶
func LoadModuleFromFilesystem(fs FS, dir string, resolvedModuleRefs *ResolvedModulesSchema) (*Module, Diagnostics)
LoadModuleFromFilesystem reads the directory at the given path in the given FS and attempts to interpret it as a Terraform module
func LoadModulesFromResolvedSchema ¶
func LoadModulesFromResolvedSchema(schemaFilePath string, filters ...ResolvedModuleSchemaFilter) ([]*Module, []Diagnostics, error)
Types ¶
type AttributeReference ¶
type DiagSeverity ¶
type DiagSeverity rune
DiagSeverity describes the severity of a Diagnostic.
const DiagError DiagSeverity = 'E'
DiagError indicates a problem that prevented proper processing of the configuration. In the precense of DiagError diagnostics the result is likely to be incomplete.
const DiagWarning DiagSeverity = 'W'
DiagWarning indicates a problem that the user may wish to consider but that did not prevent proper processing of the configuration.
func (DiagSeverity) MarshalJSON ¶
func (s DiagSeverity) MarshalJSON() ([]byte, error)
MarshalJSON is an implementation of encoding/json.Marshaler
type Diagnostic ¶
type Diagnostic struct { Severity DiagSeverity `json:"severity"` Summary string `json:"summary"` Detail string `json:"detail,omitempty"` // Pos is not populated for all diagnostics, but when populated should // indicate a particular line that the described problem relates to. Pos *SourcePos `json:"pos,omitempty"` }
Diagnostic describes a problem (error or warning) encountered during configuration loading.
type Diagnostics ¶
type Diagnostics []Diagnostic
Diagnostics represents a sequence of diagnostics. This is the type that should be returned from a function that might generate diagnostics.
func (Diagnostics) Err ¶
func (diags Diagnostics) Err() error
Err returns an error representing the receiver if the receiver HasErrors, or nil otherwise.
The returned error can be type-asserted back to a Diagnostics if needed.
func (Diagnostics) Error ¶
func (diags Diagnostics) Error() string
func (Diagnostics) HasErrors ¶
func (diags Diagnostics) HasErrors() bool
HasErrors returns true if there is at least one Diagnostic of severity DiagError in the receiever.
If a function returns a Diagnostics without errors then the result can be assumed to be complete within the "best effort" constraints of this library. If errors are present then the caller may wish to employ more caution in relying on the result.
type FS ¶
type FS interface { Open(name string) (File, error) ReadFile(name string) ([]byte, error) ReadDir(dirname string) ([]os.FileInfo, error) }
FS is an interface used by LoadModuleFromFilesystem.
Unfortunately this package implemented a draft version of the io/fs.FS API before it was finalized and so this interface is not compatible with the final design. To use this package with the final filesystem API design, use WrapFS to wrap a standard filesystem implementation so that it implements this interface.
type Local ¶
type Local struct { Name string `json:"name"` Expression hcl.Expression `json:"expression"` ParentPos SourcePos `json:"parent_pos"` Pos SourcePos `json:"pos"` // This may include variables that themselves do not resolve into attribute value (e.g. if condition). // module "mod" { // input-name = var.variable_ref != "" ? module.mod.out_ref : other_res.attr // } Dependencies map[string]AttributeReference `json:"dependencies"` }
func (Local) GetDependencies ¶
func (b Local) GetDependencies() map[string]AttributeReference
func (Local) GetParentPos ¶
type Module ¶
type Module struct { // Path is the local filesystem directory where the module was loaded from. Path string `json:"path"` // Metadata about this module Metadata *Metadata Locals map[string]*Local Variables map[string]*Variable `json:"variables"` Outputs map[string]*Output `json:"outputs"` // All resolved input variables of this module mapped to underlying resource inputs (as <var-name>: <var-attr-path>: <res-input-refs>) // The inputs are resolved recursively (e.g. input variable of A -> module A -> module-call to B -> module B -> resource). // resource "res" { // input-name = var.module_input_variable.variable_attribute // } // resolved as module_input_variable: variable_attribute: [res.input-name] (list since one variable may get passed to multiple resources) Inputs map[string]map[string][]AttributeReference `json:"inputs"` RequiredCore []string `json:"required_core,omitempty"` RequiredProviders map[string]*ProviderRequirement `json:"required_providers"` ProviderConfigs map[string]*ProviderConfig `json:"provider_configs,omitempty"` ManagedResources map[string]*Resource `json:"managed_resources"` DataResources map[string]*Resource `json:"data_resources"` ModuleCalls map[string]*ModuleCall `json:"module_calls"` // Diagnostics records any errors and warnings that were detected during // loading, primarily for inclusion in serialized forms of the module // since this slice is also returned as a second argument from LoadModule. Diagnostics Diagnostics `json:"diagnostics,omitempty"` }
Module is the top-level type representing a parsed and processed Terraform module.
func (*Module) AddResourceReference ¶
func (m *Module) AddResourceReference(srcResource AttributeReference, dstResource ResourceAttributeReference) bool
AddResourceReference maps a given dstResource attribute from this module to another srcResource attribute within this module or its sub-modules.
resource "destination_resource" { attr = source_resource.attribute.path }
func (Module) GetResourceAttributeReferences ¶
func (m Module) GetResourceAttributeReferences(varName string) []RelativeAttributeReference
GetResourceAttributeReferences recursively resolves a given variable name to underlying resource reference. It follows the variable to any sub-module calls and returns all resources it gets passed into.
type ModuleCall ¶
type ModuleCall struct { Name string `json:"name"` Source string `json:"source"` Version string `json:"version,omitempty"` Pos SourcePos `json:"pos"` // All resolved input values to this module call (as <module-input-name>: <value-ref>). // The <module-input-name> maps to an input variable in the called module. // module "mod" { // input-name = value-ref (i.e. var.variable_ref, module.mod.out_ref, other_res.attr) // } Inputs map[string]AttributeReference `json:"inputs"` // All references (not resolved) to other variables (e.g. modules, variables) grouped by name. // This may include variables that themselves do not resolve into attribute value (e.g. if condition). // module "mod" { // input-name = var.variable_ref != "" ? module.mod.out_ref : other_res.attr // } Dependencies map[string]AttributeReference `json:"dependencies"` Module *Module `json:"-"` }
ModuleCall represents a "module" block within a module. That is, a declaration of a child module from inside its parent.
func (ModuleCall) GetDependencies ¶
func (b ModuleCall) GetDependencies() map[string]AttributeReference
func (ModuleCall) GetPos ¶
func (b ModuleCall) GetPos() SourcePos
type ModuleReference ¶
func (ModuleReference) GetNormalizedKey ¶
func (m ModuleReference) GetNormalizedKey() string
type Output ¶
type Output struct { Name string `json:"name"` // Referenced resource attribute Value ResourceAttributeReference `json:"value"` Description string `json:"description,omitempty"` Sensitive bool `json:"sensitive,omitempty"` Pos SourcePos `json:"pos"` // All references (not resolved) to other variables (e.g. modules, variables) grouped by name. // This may include variables that themselves do not resolve into attribute value (e.g. if condition). // module "mod" { // input-name = var.variable_ref != "" ? module.mod.out_ref : other_res.attr // } Dependencies map[string]AttributeReference `json:"dependencies"` }
Output represents a single output from a Terraform module.
func (Output) GetDependencies ¶
func (b Output) GetDependencies() map[string]AttributeReference
func (Output) GetDescription ¶
func (Output) IsComputed ¶
func (Output) IsRequired ¶
type ParserContext ¶
type ParserContext struct { // Reference to the parent Terraform module Module *Module // Reference to the parent Resource block within the module Resource *Resource // Reference to the parent ModuleCall block within the module ModuleCall *ModuleCall // When parsing block attributes this is the name of the block itself // resource "res" { // dynamic "block-name" { // attr = var.value // } // } BlockName string // A block can be repeated for each item from a given collection (for_each attribute). // Each item can be referenced inside the block with each.* in case of top level resource or // block-label.* in case of dynamic block. // This structure holds references to accessible iterators by reference name. Iterators map[string]*ResourceAttributeReference // Path segment to be pre-pended to all attribute paths PathRoot string Logger *log.Logger }
func (*ParserContext) AddIterator ¶
func (c *ParserContext) AddIterator(refName string, value ResourceAttributeReference) *ParserContext
func (ParserContext) Copy ¶
func (c ParserContext) Copy() *ParserContext
type ProviderConfig ¶
type ProviderConfig struct { Name string `json:"name"` Alias string `json:"alias,omitempty"` Pos SourcePos `json:"pos"` }
ProviderConfig represents a provider block in the configuration
type ProviderRef ¶
type ProviderRef struct { Name string `json:"name"` Alias string `json:"alias,omitempty"` // Empty if the default provider configuration is referenced }
ProviderRef is a reference to a provider configuration within a module. It represents the contents of a "provider" argument in a resource, or a value in the "providers" map for a module call.
type ProviderRequirement ¶
type ProviderRequirement struct { Source string `json:"source,omitempty"` VersionConstraints []string `json:"version_constraints,omitempty"` ConfigurationAliases []ProviderRef `json:"aliases,omitempty"` ParentPos *SourcePos `json:"parent_pos"` // optional Pos SourcePos `json:"pos"` }
func (ProviderRequirement) GetParentPos ¶
func (b ProviderRequirement) GetParentPos() *SourcePos
func (ProviderRequirement) GetPos ¶
func (b ProviderRequirement) GetPos() SourcePos
type RelativeAttributeReference ¶
type RelativeAttributeReference struct { ResourceAttributeReference RelativePath []string `json:"relative_path"` // appended to the base ResourceReference }
func (RelativeAttributeReference) PathSegments ¶
func (r RelativeAttributeReference) PathSegments() []string
type ResolvedModuleSchemaFilter ¶
type ResolvedModuleSchemaFilter func(ResolvedModulesSchema) ResolvedModulesSchema
type ResolvedModulesSchema ¶
type ResolvedModulesSchema struct { Modules []ModuleReference // contains filtered or unexported fields }
func FilterModulesKeepTopLevel ¶
func FilterModulesKeepTopLevel(s ResolvedModulesSchema) ResolvedModulesSchema
func FilterModulesOmitHidden ¶
func FilterModulesOmitHidden(s ResolvedModulesSchema) ResolvedModulesSchema
func FilterModulesOmitLocal ¶
func FilterModulesOmitLocal(s ResolvedModulesSchema) ResolvedModulesSchema
func (ResolvedModulesSchema) Find ¶
func (s ResolvedModulesSchema) Find(path string) *ModuleReference
func (ResolvedModulesSchema) Get ¶
func (s ResolvedModulesSchema) Get(source string, version string) (path string)
func (ResolvedModulesSchema) GetPaths ¶
func (s ResolvedModulesSchema) GetPaths() (paths []string)
func (*ResolvedModulesSchema) UnmarshalFromFile ¶
func (s *ResolvedModulesSchema) UnmarshalFromFile(schemaFilePath string) error
type Resource ¶
type Resource struct { Mode ResourceMode `json:"mode"` Type string `json:"type"` Name string `json:"name"` Provider ProviderRef `json:"provider"` // All resolved input values to this resource (as <res-input-name>: <value-ref>). // resource "res" { // input-name = value-ref (i.e. var.variable_ref, module.mod.out_ref, other_res.attr) // } Inputs map[string]AttributeReference `json:"inputs"` // All references to this resource's attributes by other resoures. References map[string][]AttributeReference `json:"references"` // All references (not resolved) to other variables (e.g. modules, variables) grouped by name. // This may include variables that themselves do not resolve into attribute value (e.g. if condition). // module "mod" { // input-name = var.variable_ref != "" ? module.mod.out_ref : other_res.attr // } Dependencies map[string]AttributeReference `json:"dependencies"` Pos SourcePos `json:"pos"` }
Resource represents a single "resource" or "data" block within a module.
func (Resource) GeProviderName ¶
func (Resource) GetDependencies ¶
func (b Resource) GetDependencies() map[string]AttributeReference
type ResourceAttributeReference ¶
type ResourceAttributeReference struct { Expression hcl.Expression `json:"expression"` Module *Module ResourceType string `json:"resource_type"` ResourceName string `json:"resource_name"` AttributePath []string `json:"attribute_path"` }
func (ResourceAttributeReference) Attribute ¶
func (r ResourceAttributeReference) Attribute() string
func (*ResourceAttributeReference) CopyValues ¶
func (r *ResourceAttributeReference) CopyValues(other ResourceAttributeReference) *ResourceAttributeReference
CopyValues copies attribute values from the other instance while keeping the original metadata (i.e. expression and module references)
func (ResourceAttributeReference) MakeRelative ¶
func (r ResourceAttributeReference) MakeRelative(relativePath []string) RelativeAttributeReference
func (ResourceAttributeReference) Name ¶
func (r ResourceAttributeReference) Name() string
func (ResourceAttributeReference) Path ¶
func (r ResourceAttributeReference) Path() string
func (ResourceAttributeReference) PathSegments ¶
func (r ResourceAttributeReference) PathSegments() []string
func (ResourceAttributeReference) Pos ¶
func (r ResourceAttributeReference) Pos() (string, int)
func (ResourceAttributeReference) Root ¶
func (r ResourceAttributeReference) Root() string
func (ResourceAttributeReference) RootExpression ¶
func (r ResourceAttributeReference) RootExpression() hcl.Expression
func (ResourceAttributeReference) String ¶
func (r ResourceAttributeReference) String() string
func (ResourceAttributeReference) Type ¶
func (r ResourceAttributeReference) Type() string
type ResourceMode ¶
type ResourceMode rune
ResourceMode represents the "mode" of a resource, which is used to distinguish between managed resources ("resource" blocks in config) and data resources ("data" blocks in config).
const DataResourceMode ResourceMode = 'D'
const InvalidResourceMode ResourceMode = 0
const ManagedResourceMode ResourceMode = 'M'
func (ResourceMode) MarshalJSON ¶
func (m ResourceMode) MarshalJSON() ([]byte, error)
MarshalJSON implements encoding/json.Marshaler.
func (ResourceMode) String ¶
func (m ResourceMode) String() string
type SourcePos ¶
type SourcePos struct { Filename string `json:"filename"` Line int `json:"line"` EndLine int `json:"end_line"` StartByte int EndByte int }
SourcePos is a pointer to a particular location in a source file.
This type is embedded into other structs to allow callers to locate the definition of each described module element. The SourcePos of an element is usually the first line of its definition, although the definition can be a little "fuzzy" with JSON-based config files.
type Variable ¶
type Variable struct { Name string `json:"name"` Type string `json:"type,omitempty"` Description string `json:"description,omitempty"` // Default is an approximate representation of the default value in // the native Go type system. The conversion from the value given in // configuration may be slightly lossy. Only values that can be // serialized by json.Marshal will be included here. Default interface{} `json:"default"` Required bool `json:"required"` Sensitive bool `json:"sensitive,omitempty"` Pos SourcePos `json:"pos"` }
Variable represents a single variable from a Terraform module.