parser

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: 11 Imported by: 0

README

pkg/dataplane/parser

Parses HAProxy configuration text into a typed StructuredConfig that the comparator can diff. Wraps github.com/haproxytech/client-native so the rest of the controller doesn't have to deal with that library's direct API.

Usage

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

p, err := parser.New()
if err != nil {
    return err
}

cfg, err := p.ParseFromString(haproxyConfig)
if err != nil {
    return err        // syntax error — wrap in pkg/dataplane.ParseError if you're on the public path
}

// cfg exposes Global, Defaults, Frontends, Backends, Peers, Resolvers,
// Mailers, Caches, Rings, HTTPErrors, Userlists, Programs, LogForwards,
// FCGIApps, CrtStores, LogProfiles (v3.1+), Traces (v3.1+),
// AcmeProviders (v3.2+), plus the Enterprise sections (UDPLBs,
// WAFProfiles, BotMgmtProfiles, etc.) when an Enterprise parser is used.

Creation is not free — New constructs a client-native parser and pre-initialises its section registry. Cache the *Parser if you're parsing many configurations.

Pointer-Based Child Indexes

Beyond the section slices, the parser builds pointer-based indexes for child resources that comparators iterate hot:

  • cfg.ServerIndexbackend name → server name → *Server
  • cfg.ServerTemplateIndexbackend name → template prefix → *ServerTemplate
  • cfg.BindIndexfrontend name → bind name → *Bind
  • cfg.PeerEntryIndexpeer section name → peer entry name → *PeerEntry
  • cfg.NameserverIndexresolver name → nameserver name → *Nameserver
  • cfg.MailerEntryIndexmailers section name → mailer entry name → *MailerEntry
  • cfg.UserIndexuserlist name → username → *User
  • cfg.GroupIndexuserlist name → group name → *Group

The corresponding value maps inside the parent models (e.g. Backend.Servers) are left nil — callers should use the indexes above to avoid copying large structs (models.Server is ~1.5 KB) on every iteration. Comparators in pkg/dataplane/comparator already do this; new code that walks servers/binds/etc. should follow the same pattern.

What This Package Is Not

  • Not a validator. ParseFromString fails on syntactically invalid input only. Semantic checks (cross-references, haproxy -c) are pkg/dataplane/validator.go / pkg/dataplane.ValidateConfiguration.
  • Not for single-directive lookups. If you want "does this config have frontend X?" you operate on the returned StructuredConfig, you don't reparse.
  • Not an authoring API. Emitting HAProxy config is the template engine's job; the parser only reads.

See Also

  • pkg/dataplane — validation + sync entry points that wrap this parser
  • pkg/dataplane/comparator — consumer of StructuredConfig
  • pkg/dataplane/CLAUDE.md — client-native limitations, parser error wrapping

License

Apache-2.0 — see root LICENSE.

Documentation

Overview

Package parser provides HAProxy configuration parsing using client-native library.

This package wraps the haproxytech/client-native parser to parse HAProxy configurations from strings (in-memory, no disk I/O) into structured representations suitable for comparison and API operations.

Semantic validation (checking resource availability, directive compatibility, etc.) is NOT performed here - that is handled by the external haproxy binary in later stages.

Index

Constants

View Source
const ParsedConfigCacheSize = 4

ParsedConfigCacheSize defines the number of parsed configurations to cache. This value balances memory usage with cache hit rate:

  • 1 slot for desired config (rendered template)
  • 2 slots for current configs (one per HAProxy pod)
  • 1 extra slot for rolling update transitions

With 4 slots at ~34 MB each, the cache uses ~136 MB instead of ~544 MB with 16 slots. LRU eviction ensures the most recently used configs are retained.

Variables

This section is empty.

Functions

func CacheStats

func CacheStats() (hits, misses int64)

CacheStats returns the current cache hit/miss statistics. Useful for debugging and metrics.

func NormalizeConfigMetadata

func NormalizeConfigMetadata(config *parserconfig.StructuredConfig)

NormalizeConfigMetadata normalizes all Metadata fields in a StructuredConfig from nested API format to flat client-native format.

This ensures consistent format for comparison regardless of where config was parsed from. When the Dataplane API stores configs with metadata, it converts flat format to nested JSON. When we parse that config back, the metadata comes back in nested format, but the desired config (from template) has flat format. This mismatch causes false positive updates during comparison.

This function walks all models in the config and normalizes their Metadata fields. It uses pointer indexes for zero-copy iteration over nested elements.

func NormalizeMetadata

func NormalizeMetadata(m map[string]any) map[string]any

NormalizeMetadata converts nested API metadata format to flat client-native format.

When the Dataplane API stores configurations, comments containing metadata are stored in JSON format like: # {"comment":{"value":"Pod: echo-server"}}

When client-native parses this JSON comment, it returns the nested structure directly. However, when templates render configs, they produce flat metadata: {"comment": "Pod: echo-server"}

This format mismatch causes false positive updates during comparison. This function normalizes nested metadata to flat format for consistent comparison.

Input (nested): {"comment": {"value": "Pod: echo-server"}, "custom": {"value": "foo"}} Output (flat): {"comment": "Pod: echo-server", "custom": "foo"}

If the input is already flat, nil, or empty, it returns unchanged (or nil for nil/empty).

This function mutates the map in-place to avoid allocating a new map on every call. This is safe because maps come from the client-native parser (freshly allocated per parse) and parsed configs are cached after normalization.

Types

type Parser

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

Parser wraps client-native's config-parser for parsing HAProxy configurations.

func New

func New() (*Parser, error)

New creates a new Parser instance.

The parser uses client-native's config-parser which provides robust parsing of HAProxy configuration syntax without requiring file I/O.

func (*Parser) ParseFromString

func (p *Parser) ParseFromString(config string) (*StructuredConfig, error)

ParseFromString parses a HAProxy configuration string into a structured representation.

The configuration string should contain valid HAProxy configuration syntax. Returns a StructuredConfig containing all parsed sections (global, defaults, frontends, backends, etc.) suitable for comparison and synchronization.

Syntax validation is performed as part of parsing - any syntax errors will be returned. Semantic validation (resource availability, directive compatibility) is performed by HAProxy via the Dataplane API during configuration application.

Example:

config := `
global
    daemon
defaults
    mode http
backend web
    balance roundrobin
    server srv1 192.168.1.10:80
`
// p is a *Parser; the variable name avoids shadowing the imported
// `parser` package so subsequent parser.X calls (e.g. types) keep working.
p, _ := parser.New()
structured, err := p.ParseFromString(config)

type StructuredConfig

type StructuredConfig = parserconfig.StructuredConfig

StructuredConfig is a type alias for types.StructuredConfig. This alias is provided for backward compatibility with existing code. New code should import from haptic/pkg/dataplane/parser/parserconfig.

Directories

Path Synopsis
Package enterprise provides HAProxy Enterprise Edition configuration parsing.
Package enterprise provides HAProxy Enterprise Edition configuration parsing.
parsers
Package parsers provides wrapper parsers for HAProxy Enterprise Edition directives.
Package parsers provides wrapper parsers for HAProxy Enterprise Edition directives.
Package parserconfig provides canonical configuration types for HAProxy parsing.
Package parserconfig provides canonical configuration types for HAProxy parsing.
Package sectionextract extracts standard (Community Edition) HAProxy sections from a client-native config-parser into a parserconfig.StructuredConfig.
Package sectionextract extracts standard (Community Edition) HAProxy sections from a client-native config-parser into a parserconfig.StructuredConfig.

Jump to

Keyboard shortcuts

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