tflint

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 30, 2026 License: Apache-2.0 Imports: 2 Imported by: 1

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

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.

type Severity

type Severity int

Severity represents the severity level of an issue. Values align with tflint-plugin-sdk for ecosystem familiarity.

const (
	// ERROR indicates a critical issue (e.g., breaking change causing recreation).
	ERROR Severity = iota + 1
	// WARNING indicates a potential issue that may need attention.
	WARNING
	// NOTICE indicates an informational finding.
	NOTICE
)

func (Severity) String

func (s Severity) String() string

String returns the string representation of the severity.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL