Documentation
¶
Overview ¶
Package tflint provides tflint-aligned interfaces for tfbreak plugins.
This package contains the core types, interfaces, and utilities needed to build tfbreak plugins. The naming and structure align with tflint-plugin-sdk for ecosystem familiarity, but with adaptations for tfbreak's dual-config comparison model.
Key types:
- Severity: Issue severity levels (ERROR, WARNING, NOTICE)
- DefaultRule: Embeddable struct providing default Rule method implementations
- Rule: Interface that plugins implement for each detection rule
- Runner: Interface providing config access and issue emission (dual-config model)
- RuleSet: Interface for plugin registration and rule enumeration
- BuiltinRuleSet: Embeddable struct providing default RuleSet implementations
Index ¶
- type BuiltinRuleSet
- func (rs *BuiltinRuleSet) ApplyConfig(_ *hclext.BodyContent) error
- func (rs *BuiltinRuleSet) ApplyGlobalConfig(config *Config) error
- func (rs *BuiltinRuleSet) BuiltinImpl() *BuiltinRuleSet
- func (rs *BuiltinRuleSet) ConfigSchema() *hclext.BodySchema
- func (rs *BuiltinRuleSet) EnabledRules() []Rule
- func (rs *BuiltinRuleSet) GetRule(name string) Rule
- func (rs *BuiltinRuleSet) IsRuleEnabled(name string) bool
- func (rs *BuiltinRuleSet) NewRunner(runner Runner) (Runner, error)
- func (rs *BuiltinRuleSet) RuleNames() []string
- func (rs *BuiltinRuleSet) RuleSetName() string
- func (rs *BuiltinRuleSet) RuleSetVersion() string
- func (rs *BuiltinRuleSet) VersionConstraint() string
- type Config
- type DefaultRule
- type ExpandMode
- type GetModuleContentHint
- type GetModuleContentOption
- type ModuleCtxType
- type Rule
- type RuleConfig
- type RuleSet
- type Runner
- type Severity
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BuiltinRuleSet ¶
type BuiltinRuleSet struct {
// Name is the ruleset name (e.g., "azurerm").
Name string
// Version is the ruleset version (e.g., "0.1.0").
Version string
// Constraint is the tfbreak version constraint (e.g., ">= 0.1.0").
Constraint string
// Rules is the list of rules in this ruleset.
Rules []Rule
// contains filtered or unexported fields
}
BuiltinRuleSet provides default implementations for the RuleSet interface. Plugin authors embed this struct and override methods as needed.
Example:
type AzurermRuleSet struct {
tflint.BuiltinRuleSet
}
rs := &AzurermRuleSet{
BuiltinRuleSet: tflint.BuiltinRuleSet{
Name: "azurerm",
Version: "0.1.0",
Constraint: ">= 0.1.0",
Rules: []tflint.Rule{&ForceNewRule{}},
},
}
func (*BuiltinRuleSet) ApplyConfig ¶
func (rs *BuiltinRuleSet) ApplyConfig(_ *hclext.BodyContent) error
ApplyConfig applies plugin-specific configuration. Default implementation does nothing. Override this method to handle custom plugin configuration.
func (*BuiltinRuleSet) ApplyGlobalConfig ¶
func (rs *BuiltinRuleSet) ApplyGlobalConfig(config *Config) error
ApplyGlobalConfig applies global tfbreak configuration. Handles DisabledByDefault and Only filtering.
func (*BuiltinRuleSet) BuiltinImpl ¶
func (rs *BuiltinRuleSet) BuiltinImpl() *BuiltinRuleSet
BuiltinImpl returns the BuiltinRuleSet itself.
func (*BuiltinRuleSet) ConfigSchema ¶
func (rs *BuiltinRuleSet) ConfigSchema() *hclext.BodySchema
ConfigSchema returns nil (no plugin-specific configuration by default). Override this method to define custom plugin configuration.
func (*BuiltinRuleSet) EnabledRules ¶
func (rs *BuiltinRuleSet) EnabledRules() []Rule
EnabledRules returns all currently enabled rules.
func (*BuiltinRuleSet) GetRule ¶
func (rs *BuiltinRuleSet) GetRule(name string) Rule
GetRule returns a rule by name, or nil if not found.
func (*BuiltinRuleSet) IsRuleEnabled ¶
func (rs *BuiltinRuleSet) IsRuleEnabled(name string) bool
IsRuleEnabled returns whether a rule is enabled. Call this after ApplyGlobalConfig.
func (*BuiltinRuleSet) NewRunner ¶
func (rs *BuiltinRuleSet) NewRunner(runner Runner) (Runner, error)
NewRunner returns the runner unchanged by default. Override this method to wrap the runner with custom behavior.
func (*BuiltinRuleSet) RuleNames ¶
func (rs *BuiltinRuleSet) RuleNames() []string
RuleNames returns the names of all rules in this ruleset.
func (*BuiltinRuleSet) RuleSetName ¶
func (rs *BuiltinRuleSet) RuleSetName() string
RuleSetName returns the name of the ruleset.
func (*BuiltinRuleSet) RuleSetVersion ¶
func (rs *BuiltinRuleSet) RuleSetVersion() string
RuleSetVersion returns the version of the ruleset.
func (*BuiltinRuleSet) VersionConstraint ¶
func (rs *BuiltinRuleSet) VersionConstraint() string
VersionConstraint returns the tfbreak version constraint.
type Config ¶
type Config struct {
// Rules maps rule names to their configuration.
Rules map[string]*RuleConfig
// DisabledByDefault indicates if rules are disabled by default.
// When true, rules must be explicitly enabled.
DisabledByDefault bool
// Only enables only these rules if set.
// Takes precedence over individual rule configurations.
Only []string
// PluginDir is the directory where plugins are installed.
PluginDir string
}
Config represents global tfbreak configuration passed to plugins. This configuration is used to enable/disable rules and provide global settings.
type DefaultRule ¶
type DefaultRule struct{}
DefaultRule provides default implementations for optional Rule interface methods. Plugin authors can embed this struct in their rule implementations to get sensible defaults for Enabled() and Severity().
Example:
type MyRule struct {
tflint.DefaultRule
}
func (r *MyRule) Name() string { return "my_rule" }
func (r *MyRule) Link() string { return "https://example.com/my_rule" }
func (r *MyRule) Check(runner Runner) error { ... }
With DefaultRule embedded, MyRule automatically gets:
- Enabled() returning true (rules are enabled by default)
- Severity() returning ERROR (the default severity)
Override these methods if your rule needs different defaults:
func (r *MyRule) Severity() tflint.Severity {
return tflint.WARNING
}
func (DefaultRule) Enabled ¶
func (r DefaultRule) Enabled() bool
Enabled returns true, indicating rules are enabled by default. Override this method to disable a rule by default.
func (DefaultRule) Severity ¶
func (r DefaultRule) Severity() Severity
Severity returns ERROR, the default severity for rules. Override this method to specify a different default severity.
type ExpandMode ¶
type ExpandMode int
ExpandMode specifies how dynamic blocks are handled.
const ( // ExpandModeNone does not expand dynamic blocks. ExpandModeNone ExpandMode = iota // ExpandModeExpand expands dynamic blocks (not currently implemented). ExpandModeExpand )
type GetModuleContentHint ¶
type GetModuleContentHint struct {
// ResourceType hints at the expected resource type for optimization.
ResourceType string
}
GetModuleContentHint provides optimization hints for content retrieval.
type GetModuleContentOption ¶
type GetModuleContentOption struct {
// ModuleCtx specifies which module context to use.
ModuleCtx ModuleCtxType
// ExpandMode specifies how to handle dynamic blocks.
ExpandMode ExpandMode
// Hint provides hints for optimization.
Hint GetModuleContentHint
}
GetModuleContentOption configures how content is retrieved. Aligns with tflint-plugin-sdk's option struct.
type ModuleCtxType ¶
type ModuleCtxType int
ModuleCtxType specifies the module context for content retrieval.
const ( // ModuleCtxSelf retrieves content from the current module only. ModuleCtxSelf ModuleCtxType = iota // ModuleCtxRoot retrieves content from the root module. ModuleCtxRoot // ModuleCtxAll retrieves content from all modules. ModuleCtxAll )
type Rule ¶
type Rule interface {
// Name returns the unique name of the rule.
// Convention: lowercase with underscores (e.g., "azurerm_force_new").
Name() string
// Enabled returns whether the rule is enabled by default.
// Most rules return true; embed DefaultRule for this behavior.
Enabled() bool
// Severity returns the default severity level for issues.
// Most rules return ERROR; embed DefaultRule for this behavior.
Severity() Severity
// Link returns a URL to documentation about the rule.
// Should explain what the rule checks and how to resolve issues.
Link() string
// Check executes the rule against the configurations accessible via runner.
// Call runner.EmitIssue() for each finding.
// Return an error only for unexpected failures, not for findings.
Check(runner Runner) error
}
Rule is the interface that all tfbreak rules must implement. This aligns with tflint-plugin-sdk's Rule interface for ecosystem familiarity.
Plugin authors typically embed DefaultRule to get default implementations for Enabled() and Severity(), then implement the remaining methods.
Example:
type MyRule struct {
tflint.DefaultRule
}
func (r *MyRule) Name() string { return "my_rule" }
func (r *MyRule) Link() string { return "https://example.com/my_rule" }
func (r *MyRule) Check(runner tflint.Runner) error {
// Access old and new configs via runner
oldContent, _ := runner.GetOldResourceContent("azurerm_resource_group", schema, nil)
newContent, _ := runner.GetNewResourceContent("azurerm_resource_group", schema, nil)
// Compare and emit issues
return nil
}
type RuleConfig ¶
type RuleConfig struct {
// Name is the rule name.
Name string
// Enabled indicates if the rule is enabled.
Enabled bool
// Body is the raw HCL body for rule-specific configuration.
// Rules can decode this using runner.DecodeRuleConfig().
Body hcl.Body
}
RuleConfig represents configuration for a single rule.
type RuleSet ¶
type RuleSet interface {
// RuleSetName returns the name of the ruleset (e.g., "azurerm").
RuleSetName() string
// RuleSetVersion returns the version of the ruleset (e.g., "0.1.0").
RuleSetVersion() string
// RuleNames returns the names of all rules in this ruleset.
RuleNames() []string
// VersionConstraint returns the tfbreak version constraint (e.g., ">= 0.1.0").
VersionConstraint() string
// ConfigSchema returns the schema for plugin-specific configuration.
// Return nil if no configuration is needed.
ConfigSchema() *hclext.BodySchema
// ApplyGlobalConfig applies global tfbreak configuration.
// Called before ApplyConfig.
ApplyGlobalConfig(*Config) error
// ApplyConfig applies plugin-specific configuration.
// The content matches the schema from ConfigSchema().
ApplyConfig(*hclext.BodyContent) error
// NewRunner optionally wraps the runner with custom behavior.
// Return the runner unchanged if no customization is needed.
NewRunner(Runner) (Runner, error)
// BuiltinImpl returns the embedded BuiltinRuleSet.
// Used internally for rule iteration.
BuiltinImpl() *BuiltinRuleSet
}
RuleSet is implemented by plugins to provide a collection of rules. Plugins typically embed BuiltinRuleSet and override methods as needed.
Example:
type MyRuleSet struct {
tflint.BuiltinRuleSet
}
func main() {
plugin.Serve(&plugin.ServeOpts{
RuleSet: &MyRuleSet{
BuiltinRuleSet: tflint.BuiltinRuleSet{
Name: "myplugin",
Version: "0.1.0",
Rules: []tflint.Rule{&MyRule{}},
},
},
})
}
type Runner ¶
type Runner interface {
// GetOldModuleContent retrieves module content from the OLD (baseline) configuration.
// Use this to access the state before the change.
GetOldModuleContent(schema *hclext.BodySchema, opts *GetModuleContentOption) (*hclext.BodyContent, error)
// GetNewModuleContent retrieves module content from the NEW configuration.
// Use this to access the state after the change.
GetNewModuleContent(schema *hclext.BodySchema, opts *GetModuleContentOption) (*hclext.BodyContent, error)
// GetOldResourceContent retrieves resources of a specific type from the OLD configuration.
// This is a convenience method that filters module content for a specific resource type.
//
// Example:
//
// content, err := runner.GetOldResourceContent("azurerm_resource_group", &hclext.BodySchema{
// Attributes: []hclext.AttributeSchema{
// {Name: "location", Required: true},
// },
// }, nil)
GetOldResourceContent(resourceType string, schema *hclext.BodySchema, opts *GetModuleContentOption) (*hclext.BodyContent, error)
// GetNewResourceContent retrieves resources of a specific type from the NEW configuration.
// This is a convenience method that filters module content for a specific resource type.
//
// Example:
//
// content, err := runner.GetNewResourceContent("azurerm_resource_group", &hclext.BodySchema{
// Attributes: []hclext.AttributeSchema{
// {Name: "location", Required: true},
// },
// }, nil)
GetNewResourceContent(resourceType string, schema *hclext.BodySchema, opts *GetModuleContentOption) (*hclext.BodyContent, error)
// EmitIssue reports a finding from the rule.
// The issueRange should point to the relevant location in the NEW configuration.
// For breaking changes, this is typically where the problematic change was made.
//
// Example:
//
// if oldLocation != newLocation {
// runner.EmitIssue(rule, "location: ForceNew attribute changed", newAttr.Range)
// }
EmitIssue(rule Rule, message string, issueRange hcl.Range) error
// DecodeRuleConfig retrieves and decodes the rule's configuration.
// The target should be a pointer to a struct with hcl tags.
// Returns nil if no configuration is provided for the rule.
//
// Example:
//
// type MyRuleConfig struct {
// IgnorePatterns []string `hcl:"ignore_patterns,optional"`
// }
// var config MyRuleConfig
// if err := runner.DecodeRuleConfig("my_rule", &config); err != nil {
// return err
// }
DecodeRuleConfig(ruleName string, target any) error
}
Runner provides access to Terraform configurations during rule execution.
DEVIATION FROM TFLINT (see ADR-0001): Unlike tflint's Runner which accesses a single configuration, tfbreak's Runner provides dual-config access via GetOld* and GetNew* methods. This is because tfbreak compares two configurations to detect breaking changes.
tflint: runner.GetResourceContent(...) // Single config
tfbreak: runner.GetOldResourceContent(...) // Old (baseline) config
runner.GetNewResourceContent(...) // New (changed) config
The old configuration represents the baseline state before the change. The new configuration represents the state after the change. Rules compare these to detect breaking changes.