Documentation
¶
Overview ¶
Package testrunner implements validation test execution for HAProxyTemplateConfig.
This package provides a test runner that executes embedded validation tests defined in HAProxyTemplateConfig CRDs. It can be used both by the CLI (controller validate command) and by the admission webhook for validation.
The test runner:
- Creates resource stores from test fixtures
- Renders templates with fixture context
- Runs assertions against rendered output
- Returns structured test results
This is a pure component with no EventBus dependency - it's called directly by the CLI and by the DryRunValidator component.
Index ¶
- func CreateHTTPStoreFromFixtures(fixtures []config.HTTPResourceFixture, logger *slog.Logger) *httpstore.HTTPStore
- func FormatResults(results *TestResults, options OutputOptions) (string, error)
- func MergeFixtures(globalFixtures, testFixtures map[string][]interface{}) map[string][]interface{}
- func MergeHTTPFixtures(globalFixtures, testFixtures []config.HTTPResourceFixture) []config.HTTPResourceFixture
- type AssertionResult
- type FixtureHTTPStoreWrapper
- type Options
- type OutputFormat
- type OutputOptions
- type Runner
- type TestResult
- type TestResults
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CreateHTTPStoreFromFixtures ¶
func CreateHTTPStoreFromFixtures(fixtures []config.HTTPResourceFixture, logger *slog.Logger) *httpstore.HTTPStore
CreateHTTPStoreFromFixtures creates an HTTPStore pre-populated with fixture content.
Parameters:
- fixtures: HTTP fixtures from test definition
- logger: Logger for debug messages
Returns:
- HTTPStore with fixtures loaded as accepted content
func FormatResults ¶
func FormatResults(results *TestResults, options OutputOptions) (string, error)
FormatResults formats test results according to the specified options.
func MergeFixtures ¶
MergeFixtures deep merges global fixtures with test fixtures by resource identity.
Resource identity is defined by: apiVersion + kind + namespace + name
Merge strategy:
- Global fixtures are added first
- Test fixtures override global fixtures when same resource identity exists
- Resource types not in global fixtures are taken from test fixtures
Parameters:
- globalFixtures: Fixtures from validationTests._global
- testFixtures: Fixtures from specific test
Returns:
- Merged fixtures map (resource type → list of resources)
func MergeHTTPFixtures ¶
func MergeHTTPFixtures(globalFixtures, testFixtures []config.HTTPResourceFixture) []config.HTTPResourceFixture
MergeHTTPFixtures merges global and test-specific HTTP fixtures.
Test-specific fixtures override global fixtures for the same URL.
Parameters:
- globalFixtures: HTTP fixtures from _global test
- testFixtures: HTTP fixtures from specific test
Returns:
- Merged HTTP fixtures list
Types ¶
type AssertionResult ¶
type AssertionResult struct {
// Type is the assertion type (haproxy_valid, contains, etc).
Type string
// Description is the assertion description.
Description string
// Passed is true if the assertion passed.
Passed bool
// Error contains the failure message if assertion failed.
Error string
// Target is the assertion target (e.g., "haproxy.cfg", "map:path-prefix.map").
Target string `json:"target,omitempty" yaml:"target,omitempty"`
// TargetSize is the size of the target content in bytes.
TargetSize int `json:"targetSize,omitempty" yaml:"targetSize,omitempty"`
// TargetPreview is a preview of the target content (first 200 chars, only for failed assertions).
TargetPreview string `json:"targetPreview,omitempty" yaml:"targetPreview,omitempty"`
}
AssertionResult contains the result of running a single assertion.
type FixtureHTTPStoreWrapper ¶
type FixtureHTTPStoreWrapper struct {
// contains filtered or unexported fields
}
FixtureHTTPStoreWrapper wraps an HTTPStore pre-populated with fixtures for test execution.
Unlike the production HTTPStoreWrapper, this wrapper:
- Returns content only for URLs that have fixtures loaded
- Returns an error for URLs without fixtures (ensuring all HTTP dependencies are mocked)
- Does NOT make actual HTTP requests
Template usage:
{{ http.Fetch("http://blocklist.example.com/list.txt") }}
If the URL is not in fixtures, the template fails with a clear error message.
func NewFixtureHTTPStoreWrapper ¶
func NewFixtureHTTPStoreWrapper(store *httpstore.HTTPStore, logger *slog.Logger) *FixtureHTTPStoreWrapper
NewFixtureHTTPStoreWrapper creates a new fixture-only HTTP wrapper.
Parameters:
- store: HTTPStore pre-populated with fixtures via LoadFixture()
- logger: Logger for debug messages
func (*FixtureHTTPStoreWrapper) Fetch ¶
func (w *FixtureHTTPStoreWrapper) Fetch(args ...interface{}) (interface{}, error)
Fetch returns fixture content for a URL.
Template usage (same as production wrapper):
{{ http.Fetch("http://example.com/data.txt") }}
{{ http.Fetch("http://example.com/data.txt", {"delay": "5m"}) }}
In fixture mode:
- Options (delay, timeout, etc.) are ignored
- Authentication is ignored
- Only the URL is used to look up fixture content
- Returns error if URL is not in fixtures
Returns:
- Content string if URL has fixture
- Error if URL is not in fixtures
type Options ¶
type Options struct {
// TestName filters tests to run. If empty, all tests run.
TestName string
// Logger for structured logging. If nil, uses default logger.
Logger *slog.Logger
// Workers is the number of parallel workers for test execution.
// Default: 4
// Set to 1 for sequential execution.
Workers int
// DebugFilters enables detailed filter operation logging.
// When enabled, each sort comparison is logged with values and results.
DebugFilters bool
// ProfileIncludes enables include timing profiling.
// When enabled, shows which included templates take the most time.
ProfileIncludes bool
// Capabilities defines which features are available for the local HAProxy version.
// Used to determine path resolution (e.g., CRT-list paths fallback when not supported).
Capabilities dataplane.Capabilities
}
Options configures the test runner.
type OutputFormat ¶
type OutputFormat string
OutputFormat specifies the output format for test results.
const ( // OutputFormatSummary outputs a human-readable summary. OutputFormatSummary OutputFormat = "summary" // OutputFormatJSON outputs structured JSON. OutputFormatJSON OutputFormat = "json" // OutputFormatYAML outputs structured YAML. OutputFormatYAML OutputFormat = "yaml" )
type OutputOptions ¶
type OutputOptions struct {
// Format specifies the output format (summary, json, yaml).
Format OutputFormat
// Verbose enables showing rendered content previews for failed assertions.
Verbose bool
}
OutputOptions configures output formatting.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner executes validation tests for HAProxyTemplateConfig.
It's a pure component with no EventBus dependency, designed to be called directly from the CLI or from the DryRunValidator.
func New ¶
func New( cfg *config.Config, engine templating.Engine, validationPaths *dataplane.ValidationPaths, options Options, ) *Runner
New creates a new test runner.
Parameters:
- cfg: The internal config containing templates and validation tests
- engine: Pre-compiled template engine
- validationPaths: Filesystem paths for HAProxy validation
- options: Runner options
Returns:
- A new Runner instance ready to execute tests
func (*Runner) CreateStoresFromFixtures ¶
func (r *Runner) CreateStoresFromFixtures(fixtures map[string][]interface{}) (map[string]types.Store, error)
CreateStoresFromFixtures creates resource stores from test fixtures.
This converts the test fixtures (map of resource type → list of resources) into resource stores that can be used for template rendering.
Implementation:
- Phase 1: Create empty stores for ALL watched resources
- Phase 2: Populate stores with fixture data where provided
This ensures templates can safely call .List() on any watched resource type, even if that resource type is not present in test fixtures.
Parameters:
- fixtures: Map of resource type names to lists of Kubernetes resources
Returns:
- Map of resource type names to resource stores
- error if fixture processing fails
func (*Runner) RunTests ¶
RunTests executes all validation tests (or a specific test if filtered).
This method:
- Filters tests if a specific test name was requested
- For each test: - Creates resource stores from fixtures - Renders HAProxy configuration - Runs all assertions
- Aggregates and returns results
Parameters:
- ctx: Context for cancellation and timeouts
Returns:
- TestResults containing results for all executed tests
- error if a fatal error occurred (not test failures)
type TestResult ¶
type TestResult struct {
// TestName is the name of the test.
TestName string
// Description is the test description.
Description string
// Passed is true if all assertions passed.
Passed bool
// Duration is the time taken to run this test.
Duration time.Duration
// Assertions contains results for each assertion.
Assertions []AssertionResult
// RenderError is set if template rendering failed.
RenderError string
// RenderedConfig contains the rendered HAProxy configuration (for --dump-rendered).
RenderedConfig string `json:"renderedConfig,omitempty" yaml:"renderedConfig,omitempty"`
// RenderedMaps contains rendered map files (for --dump-rendered).
RenderedMaps map[string]string `json:"renderedMaps,omitempty" yaml:"renderedMaps,omitempty"`
// RenderedFiles contains rendered general files (for --dump-rendered).
RenderedFiles map[string]string `json:"renderedFiles,omitempty" yaml:"renderedFiles,omitempty"`
// RenderedCerts contains rendered SSL certificates (for --dump-rendered).
RenderedCerts map[string]string `json:"renderedCerts,omitempty" yaml:"renderedCerts,omitempty"`
// IncludeStats contains timing statistics for included templates (for --profile-includes).
IncludeStats []templating.IncludeStats `json:"includeStats,omitempty" yaml:"includeStats,omitempty"`
}
TestResult contains the result of running a single validation test.
type TestResults ¶
type TestResults struct {
// TotalTests is the total number of tests executed.
TotalTests int
// PassedTests is the number of tests that passed all assertions.
PassedTests int
// FailedTests is the number of tests with at least one failed assertion.
FailedTests int
// TestResults contains detailed results for each test.
TestResults []TestResult
// Duration is the total time taken to run all tests.
Duration time.Duration
}
TestResults contains the results of running validation tests.
func (*TestResults) AllPassed ¶
func (r *TestResults) AllPassed() bool
AllPassed returns true if all tests passed.