diffy

package module
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Dec 27, 2025 License: MIT Imports: 19 Imported by: 0

README

diffy Go Reference

A terraform schema validation tool that ensures your infrastructure configurations are complete and compliant with provider specifications.

Automatically detects missing required properties, validates optional attributes, and helps maintain configuration quality across teams and projects.

Why diffy?

Terraform configurations can become complex and inconsistent over time. Missing required properties, outdated attribute names, and incomplete resource definitions can lead to deployment failures and configuration drift.

Diffy helps you:

Catch configuration errors before deployment

Ensure compliance with provider schema requirements

Maintain consistency across large infrastructure codebases

Reduce debugging time during infrastructure changes

Support automated validation in CI/CD pipelines

Installation

go get github.com/dkooll/diffy

Usage

See the examples/usage directory for examples and test cases.

Features

Schema Validation

Validates all Terraform resources and data sources against their provider schemas

Identifies missing required properties that would cause deployment failures

Detects deprecated or invalid attribute configurations

Supports recursive validation of nested modules and submodules

GitHub Integration

Automatically creates GitHub issues for validation findings

Provides detailed, actionable feedback on configuration problems

Enables team collaboration on infrastructure quality improvements

Flexible Configuration

Supports resource and data source exclusions for custom validation rules

Environment variable configuration for CI/CD integration

Configurable logging levels and output formats

Middleware pattern for custom validation extensions

Advanced Terraform Support

Respects Terraform lifecycle blocks and ignore_changes directives

Handles complex dynamic blocks and nested configurations

Works with all major Terraform providers and custom providers

Configuration

Environment Variables

Configure diffy through environment variables for CI/CD pipelines:

TERRAFORM_ROOT: Path to your Terraform configuration root directory

EXCLUDED_RESOURCES: Comma-separated list of resource types to exclude from validation

EXCLUDED_DATA_SOURCES: Comma-separated list of data source types to exclude

GITHUB_TOKEN: Personal access token for GitHub issue creation (optional)

Notes

The TERRAFORM_ROOT environment variable takes highest priority when set

A Terraform root path must be specified either via environment variable or configuration option

GitHub integration requires appropriate repository permissions and a valid token

Validation respects Terraform lifecycle ignore_changes directives, and diffy skips attributes that providers mark as computed-only so you can focus on values you must declare

Contributors

We welcome contributions from the community! Whether it's reporting a bug, suggesting a new feature, or submitting a pull request, your input is highly valued.

Documentation

Overview

Package diffy provides configuration options for schema validation

Package diffy validates Terraform configurations against provider schemas.

Package diffy provides core interfaces for the validation system

Package diffy provides logging implementations

Package diffy provides middleware functionality for validation operations

Package diffy provides core types and data structures

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FormatFinding

func FormatFinding(finding ValidationFinding) string

func NormalizeSource

func NormalizeSource(source string) string

Types

type Block

type Block struct {
	Type   string
	Labels []string
	Body   *Body
}

type BlockData

type BlockData struct {
	Properties    map[string]bool
	StaticBlocks  map[string][]*ParsedBlock
	DynamicBlocks map[string]*ParsedBlock
	IgnoreChanges []string
}

func NewBlockData

func NewBlockData() BlockData

func (*BlockData) ParseAttributes

func (blockData *BlockData) ParseAttributes(body *hclsyntax.Body)

func (*BlockData) ParseBlocks

func (blockData *BlockData) ParseBlocks(body *hclsyntax.Body)

func (*BlockData) Validate

func (blockData *BlockData) Validate(
	resourceType, path string,
	schema *SchemaBlock,
	parentIgnore []string,
	findings *[]ValidationFinding,
)

type BlockProcessor

type BlockProcessor interface {
	ParseAttributes(body *Body)
	ParseBlocks(body *Body)
	Validate(resourceType, path string, schema *SchemaBlock, parentIgnore []string, findings *[]ValidationFinding)
}

type Body

type Body struct {
	Attributes map[string]any
	Blocks     []*Block
}

type DefaultHCLParser

type DefaultHCLParser struct{}

func NewHCLParser

func NewHCLParser() *DefaultHCLParser

func (*DefaultHCLParser) ParseMainFile

func (parser *DefaultHCLParser) ParseMainFile(ctx context.Context, filename string) ([]ParsedResource, []ParsedDataSource, error)

func (*DefaultHCLParser) ParseProviderRequirements

func (parser *DefaultHCLParser) ParseProviderRequirements(ctx context.Context, filename string) (map[string]ProviderConfig, error)

func (*DefaultHCLParser) ParseTerraformFiles added in v1.3.0

func (parser *DefaultHCLParser) ParseTerraformFiles(_ context.Context, files []string) ([]ParsedResource, []ParsedDataSource, error)

type DefaultSchemaValidator

type DefaultSchemaValidator struct {
	// contains filtered or unexported fields
}

func NewSchemaValidator

func NewSchemaValidator(logger Logger) *DefaultSchemaValidator

func (*DefaultSchemaValidator) ValidateDataSources

func (validator *DefaultSchemaValidator) ValidateDataSources(
	dataSources []ParsedDataSource,
	schema TerraformSchema,
	providers map[string]ProviderConfig,
	dir, submoduleName string,
) []ValidationFinding

func (*DefaultSchemaValidator) ValidateResources

func (validator *DefaultSchemaValidator) ValidateResources(
	resources []ParsedResource,
	schema TerraformSchema,
	providers map[string]ProviderConfig,
	dir, submoduleName string,
) []ValidationFinding

type DefaultTerraformRunner

type DefaultTerraformRunner struct {
	// contains filtered or unexported fields
}

func NewTerraformRunner

func NewTerraformRunner() *DefaultTerraformRunner

func (*DefaultTerraformRunner) GetSchema

func (*DefaultTerraformRunner) Init

type GitHubConfig added in v1.3.0

type GitHubConfig struct {
	RepoOwner string
	RepoName  string
	Token     string
}

type GitHubError added in v1.3.0

type GitHubError struct {
	Operation string
	Message   string
	Err       error
}

func (*GitHubError) Error added in v1.3.0

func (e *GitHubError) Error() string

func (*GitHubError) Unwrap added in v1.3.0

func (e *GitHubError) Unwrap() error

type GitHubIssueManager

type GitHubIssueManager struct {
	GitHubConfig
	Client *http.Client
}

func NewGitHubIssueManager

func NewGitHubIssueManager(repoOwner, repoName, token string) *GitHubIssueManager

func (*GitHubIssueManager) CloseExistingIssuesIfEmpty added in v1.3.0

func (manager *GitHubIssueManager) CloseExistingIssuesIfEmpty(ctx context.Context) error

func (*GitHubIssueManager) CreateOrUpdateIssue

func (manager *GitHubIssueManager) CreateOrUpdateIssue(ctx context.Context, findings []ValidationFinding) error

type GitRepoInfo

type GitRepoInfo struct {
	TerraformRoot string
}

func NewGitRepoInfo

func NewGitRepoInfo(terraformRoot string) *GitRepoInfo

func (*GitRepoInfo) GetRepoInfo

func (g *GitRepoInfo) GetRepoInfo() (owner, repo string)

type HCLParser

type HCLParser interface {
	ParseProviderRequirements(ctx context.Context, filename string) (map[string]ProviderConfig, error)
	ParseMainFile(ctx context.Context, filename string) ([]ParsedResource, []ParsedDataSource, error)
	ParseTerraformFiles(ctx context.Context, filenames []string) ([]ParsedResource, []ParsedDataSource, error)
}

type IssueManager

type IssueManager interface {
	CreateOrUpdateIssue(ctx context.Context, findings []ValidationFinding) error
}

type Logger

type Logger interface {
	Logf(format string, args ...any)
}

type ParseError added in v1.3.0

type ParseError struct {
	File    string
	Message string
	Err     error
}

func (*ParseError) Error added in v1.3.0

func (e *ParseError) Error() string

func (*ParseError) Unwrap added in v1.3.0

func (e *ParseError) Unwrap() error

type ParsedBlock

type ParsedBlock struct {
	Data BlockData
}

func ParseSyntaxBody

func ParseSyntaxBody(body *hclsyntax.Body) *ParsedBlock

type ParsedDataSource

type ParsedDataSource struct {
	Type string
	Name string
	Data BlockData
}

type ParsedResource

type ParsedResource struct {
	Type string
	Name string
	Data BlockData
}

type ProviderConfig

type ProviderConfig struct {
	Source  string
	Version string
}

type ProviderSchema

type ProviderSchema struct {
	ResourceSchemas   map[string]*ResourceSchema `json:"resource_schemas"`
	DataSourceSchemas map[string]*ResourceSchema `json:"data_source_schemas"`
}

type RepositoryInfoProvider

type RepositoryInfoProvider interface {
	GetRepoInfo() (owner, name string)
}

type ResourceSchema

type ResourceSchema struct {
	Block *SchemaBlock `json:"block"`
}

type SchemaAttribute

type SchemaAttribute struct {
	Required   bool `json:"required"`
	Optional   bool `json:"optional"`
	Computed   bool `json:"computed"`
	Deprecated bool `json:"deprecated"`
}

type SchemaBlock

type SchemaBlock struct {
	Attributes map[string]*SchemaAttribute `json:"attributes"`
	BlockTypes map[string]*SchemaBlockType `json:"block_types"`
}

type SchemaBlockType

type SchemaBlockType struct {
	Nesting    string       `json:"nesting"`
	MinItems   int          `json:"min_items"`
	MaxItems   int          `json:"max_items"`
	Block      *SchemaBlock `json:"block"`
	Deprecated bool         `json:"deprecated"`
}

type SchemaValidator

type SchemaValidator interface {
	ValidateResources(resources []ParsedResource, schema TerraformSchema, providers map[string]ProviderConfig, dir, submoduleName string) []ValidationFinding
	ValidateDataSources(dataSources []ParsedDataSource, schema TerraformSchema, providers map[string]ProviderConfig, dir, submoduleName string) []ValidationFinding
}

type SchemaValidatorOption

type SchemaValidatorOption func(*SchemaValidatorOptions)

func WithExcludedDataSources added in v1.3.0

func WithExcludedDataSources(dataSources ...string) SchemaValidatorOption

func WithExcludedResources added in v1.3.0

func WithExcludedResources(resources ...string) SchemaValidatorOption

func WithGitHubIssueCreation

func WithGitHubIssueCreation() SchemaValidatorOption

func WithParser added in v1.4.0

func WithParser(parser HCLParser) SchemaValidatorOption

func WithTerraformRoot

func WithTerraformRoot(path string) SchemaValidatorOption

func WithTerraformRunner added in v1.4.0

func WithTerraformRunner(runner TerraformRunner) SchemaValidatorOption

type SchemaValidatorOptions

type SchemaValidatorOptions struct {
	TerraformRoot       string
	CreateGitHubIssue   bool
	Logger              Logger
	GitHubToken         string
	GitHubOwner         string
	GitHubRepo          string
	Silent              bool
	ExcludedResources   []string
	ExcludedDataSources []string
	Parser              HCLParser
	TerraformRunner     TerraformRunner
}

type SimpleLogger

type SimpleLogger struct{}

func (*SimpleLogger) Logf

func (l *SimpleLogger) Logf(format string, args ...any)

type SubModule

type SubModule struct {
	Name string
	Path string
}

func FindSubmodules

func FindSubmodules(modulesDir string) ([]SubModule, error)

type TerraformRunner

type TerraformRunner interface {
	Init(ctx context.Context, dir string) error
	GetSchema(ctx context.Context, dir string) (*TerraformSchema, error)
}

type TerraformSchema

type TerraformSchema struct {
	ProviderSchemas map[string]*ProviderSchema `json:"provider_schemas"`
}

type ValidationError added in v1.3.0

type ValidationError struct {
	ResourceType string
	Message      string
	Err          error
}

func (*ValidationError) Error added in v1.3.0

func (e *ValidationError) Error() string

func (*ValidationError) Unwrap added in v1.3.0

func (e *ValidationError) Unwrap() error

type ValidationFinding

type ValidationFinding struct {
	ResourceType  string
	Path          string
	Name          string
	Required      bool
	IsBlock       bool
	IsDataSource  bool
	SubmoduleName string
}

func ApplyMiddleware added in v1.3.0

func ApplyMiddleware(findings []ValidationFinding, err error, middleware ValidationMiddleware) ([]ValidationFinding, error)

func DeduplicateFindings

func DeduplicateFindings(findings []ValidationFinding) []ValidationFinding

func ValidateSchema

func ValidateSchema(options ...SchemaValidatorOption) ([]ValidationFinding, error)

func ValidateTerraformSchema

func ValidateTerraformSchema(logger Logger, dir, submoduleName string, parser HCLParser, runner TerraformRunner) ([]ValidationFinding, error)

func ValidateTerraformSchemaInDirectory

func ValidateTerraformSchemaInDirectory(logger Logger, dir, submoduleName string) ([]ValidationFinding, error)

func ValidateTerraformSchemaInDirectoryWithOptions added in v1.3.0

func ValidateTerraformSchemaInDirectoryWithOptions(logger Logger, dir, submoduleName string, excludedResources, excludedDataSources []string) ([]ValidationFinding, error)

func ValidateTerraformSchemaWithOptions added in v1.3.0

func ValidateTerraformSchemaWithOptions(logger Logger, dir, submoduleName string, parser HCLParser, runner TerraformRunner, excludedResources, excludedDataSources []string) ([]ValidationFinding, error)

type ValidationMiddleware added in v1.3.0

type ValidationMiddleware func([]ValidationFinding, error) ([]ValidationFinding, error)

func LoggingMiddleware added in v1.3.0

func LoggingMiddleware(logger Logger) ValidationMiddleware

Jump to

Keyboard shortcuts

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