comparator

package
v0.2.0-alpha.1 Latest Latest
Warning

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

Go to latest
Published: Jul 5, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

README

pkg/dataplane/comparator

Section-by-section diff between two parsed HAProxy configurations. Given a current *parser.StructuredConfig and a desired one, the comparator returns the ordered list of Operations describing what changed (plus a DiffSummary for quick decisions like "does anything need to be deployed at all?"). The orchestrator uses the diff to decide whether a full raw-config push is needed and, if only server addresses changed, whether to apply them via the runtime API without a reload.

The orchestrator (pkg/dataplane.Sync / DryRun) drives this — most callers use it via the higher-level entry points rather than instantiating a Comparator directly.

Usage

import (
    "gitlab.com/haproxy-haptic/haptic/pkg/dataplane/comparator"
    "gitlab.com/haproxy-haptic/haptic/pkg/dataplane/parser"
)

p, _ := parser.New()
current, _ := p.ParseFromString(currentHAProxyConfig)
desired, _ := p.ParseFromString(desiredHAProxyConfig)

comp := comparator.New()
diff, err := comp.Compare(current, desired)
if err != nil {
    return err
}

if !diff.Summary.HasChanges() {
    return nil // nothing to do
}

for _, op := range diff.Operations {
    // op.Describe() already includes the verb ("Create backend 'api'",
    // "Update server 'srv' in backend 'api'", "Delete frontend 'http'",
    // ...). op.Type() returns sections.OperationType (an int with no
    // String method); compare it against sections.OperationCreate /
    // OperationUpdate / OperationDelete if you need the category.
    fmt.Println(op.Describe())
}

Compare returns a *ConfigDiff whose Operations slice is already ordered for execution (sections first, child resources after, with priority numbers from each section's comparator). The Summary carries pre-aggregated counters (TotalCreates, TotalUpdates, TotalDeletes, plus per-section booleans like GlobalChanged) — handy for log lines and the runtime-vs-reload decision in the orchestrator.

What This Package Is Not

  • Not a parser. Take a *parser.StructuredConfig from pkg/dataplane/parser.
  • Not an executor. Operations describe what to do; the orchestrator in pkg/dataplane consumes them to decide push strategy (raw-config push for structural changes, runtime server-field updates for address-only changes).
  • Not a validator. No semantic checks here; bad configs come in as parser errors before this package even runs.

See Also

  • pkg/dataplaneSync / DryRun / Diff entry points that wrap this comparator
  • pkg/dataplane/comparator/sections — section-specific comparison logic (one file per HAProxy section type)
  • pkg/dataplane/CLAUDE.md — comparator design notes, adding a new section comparator

License

Apache-2.0 — see root LICENSE.

Documentation

Overview

Package comparator provides comparison functions for HAProxy Enterprise Edition sections.

This file contains comparison functions for EE-only sections: - Bot Management Profiles (v3.0+ EE) - Captcha (v3.0+ EE) - WAF Profile (v3.2+ EE) - WAF Global (v3.2+ EE)

Package comparator provides fine-grained configuration comparison and operation generation for HAProxy Dataplane API synchronization.

The comparator performs attribute-level comparison between current and desired configurations, generating the minimal set of operations needed to transform one into the other.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Comparator

type Comparator struct{}

Comparator performs fine-grained comparison between HAProxy configurations.

It generates the minimal set of operations needed to transform a current configuration into a desired configuration, using attribute-level granularity to minimize API calls and avoid unnecessary HAProxy reloads.

func New

func New() *Comparator

New creates a new Comparator instance.

func (*Comparator) Compare

func (c *Comparator) Compare(current, desired *parser.StructuredConfig) (*ConfigDiff, error)

Compare performs a deep comparison between current and desired configurations.

It returns a ConfigDiff containing all operations needed to transform current into desired, along with a summary of changes.

The comparison is performed at attribute-level granularity - if only a single attribute changes (e.g., server weight), only that attribute is updated rather than replacing the entire resource.

Example:

// cmp is a *Comparator; the variable name avoids shadowing the
// imported `comparator` package so subsequent comparator.X type
// references in the same scope keep working.
cmp := comparator.New()
diff, err := cmp.Compare(currentConfig, desiredConfig)
if err != nil {
    slog.Error("Comparison failed", "error", err)
    os.Exit(1)
}

fmt.Printf("Changes: %s\n", diff.Summary.String())
for _, op := range diff.Operations {
    fmt.Printf("- %s\n", op.Describe())
}

type ConfigDiff

type ConfigDiff struct {
	// Operations is the ordered list of operations to execute
	Operations []Operation

	// Summary provides a high-level overview of changes
	Summary DiffSummary
}

ConfigDiff represents the difference between two HAProxy configurations.

It contains all operations needed to transform the current configuration into the desired configuration, along with a summary of changes.

type DiffSummary

type DiffSummary struct {
	// Total counts by operation type
	TotalCreates int
	TotalUpdates int
	TotalDeletes int

	// Global and defaults changes
	GlobalChanged   bool
	DefaultsChanged bool

	// Frontend changes
	FrontendsAdded    []string
	FrontendsModified []string
	FrontendsDeleted  []string

	// Backend changes
	BackendsAdded    []string
	BackendsModified []string
	BackendsDeleted  []string

	// Server changes (map of backend -> server names)
	ServersAdded    map[string][]string
	ServersModified map[string][]string
	ServersDeleted  map[string][]string

	// Backend diff fields: for each modified backend, the list of BackendBase fields that differ.
	// Populated only when backend attributes (not nested collections) cause the update.
	// Useful for diagnosing false diffs from parser round-trip asymmetries.
	BackendDiffFields map[string][]string

	// Other section changes (extensible for future sections)
	OtherChanges map[string]int // section name -> count of changes
}

DiffSummary provides a high-level overview of configuration changes.

This is useful for logging, monitoring, and decision-making about whether to proceed with a configuration update.

func NewDiffSummary

func NewDiffSummary() DiffSummary

NewDiffSummary creates an empty DiffSummary with initialized maps.

func (*DiffSummary) HasChanges

func (s *DiffSummary) HasChanges() bool

HasChanges returns true if any configuration changes are present.

func (*DiffSummary) String

func (s *DiffSummary) String() string

String returns a human-readable summary of changes.

func (*DiffSummary) StructuralOperations

func (s *DiffSummary) StructuralOperations() int

StructuralOperations returns the number of operations that require HAProxy reload. This excludes server UPDATE operations which are runtime-eligible and can be applied without reload via the HAProxy Runtime API.

Use this to choose the apply strategy: zero structural operations means the diff can be applied with a skip-reload runtime push, since runtime-eligible operations should not trigger reloads.

func (*DiffSummary) TotalOperations

func (s *DiffSummary) TotalOperations() int

TotalOperations returns the total number of operations across all types.

type Operation

type Operation = sections.Operation

Operation represents a single configuration change operation.

Operations are executed within transactions and map to specific Dataplane API endpoints for atomic configuration updates.

This is an alias for sections.Operation: factory functions in the sections package return the same interface that the comparator surfaces to the rest of the dataplane package.

Directories

Path Synopsis
Package sections provides factory functions for creating HAProxy configuration operations.
Package sections provides factory functions for creating HAProxy configuration operations.

Jump to

Keyboard shortcuts

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