Documentation
¶
Overview ¶
Package renderplan holds the structure a render declares about its own output: the ordered sections of haproxy.cfg, the backend records the generator emitted them from, the map entries, and the file set.
The structure is produced by the generator (chart macros through pkg/controller/rendercontext.PlanRegistry), never by parsing HAProxy configuration. Pure data: no controller, templating or client-native imports.
Index ¶
- Constants
- Variables
- func Digest(b []byte) string
- func DigestString(s string) string
- func EqualKeywordArgs(left, right []KeywordArg) bool
- func ExactlyEqual(left, right *Plan) bool
- func FormatDigest(sum uint64) string
- func MapEntriesMatch(content string, entries []Entry) bool
- func ReconcileSnapshotWithBackendSource(authority *Authority, previous *Snapshot, plan *Plan, backends BackendSource, ...) (*Snapshot, *Delta, error)
- func ReconcileSnapshotWithConfigDocument(authority *Authority, previous *Snapshot, plan *Plan, ...) (*Snapshot, *Delta, error)
- type Authority
- type Backend
- type BackendHandle
- type BackendSource
- type CRTList
- type CRTListEntry
- type CRTListHandle
- type Changes
- type CurrentConfig
- type Delta
- func (d *Delta) Apply(base *Snapshot) (*Snapshot, error)
- func (d *Delta) Changes() (Changes, error)
- func (d *Delta) RequiresFullValidation() (bool, error)
- func (d *Delta) SameRoot() (bool, error)
- func (d *Delta) SectionChanges() ([]SequenceChange[Section], error)
- func (d *Delta) ValidateAuthentication() error
- type Entry
- type File
- type FileChange
- type FileDescriptor
- type FileGapHandle
- type FileHandle
- type FileRecord
- type KeywordArg
- type Map
- type MapHandle
- type NamedChange
- type ParsedMapEntries
- type Plan
- type Profile
- type ProfileHandle
- type Section
- type SectionGapHandle
- type SectionHandle
- type SequenceChange
- type Server
- type ServerAddr
- type Snapshot
- func (s *Snapshot) BackendHandle(name string) (*BackendHandle, bool, error)
- func (s *Snapshot) BackendNamed(name string) (Backend, bool, error)
- func (s *Snapshot) CRTListHandle(path string) (*CRTListHandle, bool, error)
- func (s *Snapshot) ExactEqual(other *Snapshot) (bool, error)
- func (s *Snapshot) FileAt(index int) (File, error)
- func (s *Snapshot) FileGapHandle(index int) (*FileGapHandle, error)
- func (s *Snapshot) FileHandle(index int) (*FileHandle, error)
- func (s *Snapshot) ID() (string, error)
- func (s *Snapshot) LegacyCopy() (*Plan, error)
- func (s *Snapshot) Len() (int, error)
- func (s *Snapshot) MapHandle(path string) (*MapHandle, bool, error)
- func (s *Snapshot) MapNamed(path string) (Map, bool, error)
- func (s *Snapshot) MarshalJSON() ([]byte, error)
- func (s *Snapshot) ProfileHandle(name string) (*ProfileHandle, bool, error)
- func (s *Snapshot) ProfileNamed(name string) (Profile, bool, error)
- func (s *Snapshot) SameRoot(other *Snapshot) (bool, error)
- func (s *Snapshot) SectionAt(index int) (Section, error)
- func (s *Snapshot) SectionGapHandle(index int) (*SectionGapHandle, error)
- func (s *Snapshot) SectionHandle(index int) (*SectionHandle, error)
- func (s *Snapshot) SectionsCopy() ([]Section, error)
- func (s *Snapshot) SharedPlan() (*Plan, error)
- func (s *Snapshot) ValidateAuthentication() error
- func (s *Snapshot) WriteJSON(target io.Writer) error
- type Transaction
- func (t *Transaction) Commit() (*Snapshot, *Delta, error)
- func (t *Transaction) DeleteBackend(expected *BackendHandle) error
- func (t *Transaction) DeleteFile(expected *FileHandle) error
- func (t *Transaction) DeleteMap(expected *MapHandle) error
- func (t *Transaction) DeleteProfile(expected *ProfileHandle) error
- func (t *Transaction) DeleteSection(expected *SectionHandle) error
- func (t *Transaction) InsertBackend(name string, backend Backend) error
- func (t *Transaction) InsertFile(expected *FileGapHandle, file File) error
- func (t *Transaction) InsertMap(path string, value Map) error
- func (t *Transaction) InsertProfile(name string, profile Profile) error
- func (t *Transaction) InsertSection(expected *SectionGapHandle, section Section) error
- func (t *Transaction) ReplaceBackend(expected *BackendHandle, backend Backend) error
- func (t *Transaction) ReplaceCRTList(expected *CRTListHandle, value CRTList) error
- func (t *Transaction) ReplaceConfigFileDocument(expected *FileHandle, document rendercontent.Document) error
- func (t *Transaction) ReplaceFile(expected *FileHandle, file File) error
- func (t *Transaction) ReplaceMap(expected *MapHandle, value Map) error
- func (t *Transaction) ReplaceProfile(expected *ProfileHandle, profile Profile) error
- func (t *Transaction) ReplaceSection(expected *SectionHandle, section Section) error
Constants ¶
const ( SectionKindCore = "core" SectionKindProfile = "profile" SectionKindBackend = "backend" )
Section kinds.
const ( ShapeDynamic = "dynamic" ShapeStructural = "structural" )
Backend shapes: a dynamic backend can be created and populated over the runtime API, a structural one needs a reload.
const ( FileKindConfig = "config" FileKindMap = "map" FileKindCert = "cert" FileKindCA = "ca" FileKindCRTList = "crtlist" FileKindGeneral = "general" )
File kinds.
const ConfigFilePath = "haproxy.cfg"
ConfigFilePath is the single main configuration path in every render plan.
const SchemaVersion = 1
SchemaVersion identifies the plan format. A consumer reading a foreign version must treat the plan as unknown rather than decode it partially.
Variables ¶
var ErrDocumentTransitionRequiresRebuild = errors.New("render plan document transition requires a full rebuild")
ErrDocumentTransitionRequiresRebuild reports a transition the sparse delta protocol cannot encode.
Functions ¶
func Digest ¶
Digest returns the xxhash64 of b as fixed-width hex. It is the only hash the plan uses, so digests from different producers are comparable.
func DigestString ¶
DigestString is Digest over a string, without copying it to a byte slice.
func EqualKeywordArgs ¶
func EqualKeywordArgs(left, right []KeywordArg) bool
EqualKeywordArgs reports whether both keyword lists declare the same keywords with the same arguments in the same order. Nil and empty lists are the same list.
func ExactlyEqual ¶
ExactlyEqual compares the complete render identity without trusting a digest. It returns false when either plan came from a blob and therefore no longer carries the controller-local exact bytes.
func FormatDigest ¶
FormatDigest renders an xxhash64 sum as the plan's 16-character hex digest.
func MapEntriesMatch ¶
MapEntriesMatch reports whether ParseMapEntries(content) would equal entries, without building the entry list: it walks the lines and compares each parsed entry in place.
func ReconcileSnapshotWithBackendSource ¶
func ReconcileSnapshotWithBackendSource( authority *Authority, previous *Snapshot, plan *Plan, backends BackendSource, document rendercontent.Document, ) (*Snapshot, *Delta, error)
ReconcileSnapshotWithBackendSource is ReconcileSnapshotWithConfigDocument with the backends read from source; plan.Backends must be nil. A previous snapshot built from an earlier state of the same source is compared over the names that changed since, not over every backend.
func ReconcileSnapshotWithConfigDocument ¶
func ReconcileSnapshotWithConfigDocument( authority *Authority, previous *Snapshot, plan *Plan, document rendercontent.Document, ) (*Snapshot, *Delta, error)
ReconcileSnapshotWithConfigDocument owns exact plan metadata while retaining config as a document.
Types ¶
type Authority ¶
type Authority struct {
// contains filtered or unexported fields
}
Authority owns one lineage of render-plan snapshots. digestFallbacks is a pointer so a shallow copy of an authority stays a copyable value, which authentication still rejects.
func NewAuthority ¶
func NewAuthority() *Authority
NewAuthority creates an isolated snapshot lineage.
func (*Authority) DigestFallbacks ¶
DigestFallbacks counts the plan digests this lineage computed by rebuilding the whole plan because the streaming canonical writer could not prove its order. It stays zero while the incremental digest engages.
func (*Authority) ValidateAuthentication ¶
ValidateAuthentication verifies the authority's exact identity.
func (*Authority) ValidateSnapshot ¶
ValidateSnapshot proves that snapshot belongs to this authority.
type Backend ¶
type Backend struct {
Name string `json:"name"`
Profile string `json:"profile,omitempty"`
Mode string `json:"mode,omitempty"`
GUID string `json:"guid,omitempty"`
Balance string `json:"balance,omitempty"`
HashType string `json:"hashType,omitempty"`
Shape string `json:"shape"`
ShapeReason string `json:"shapeReason,omitempty"`
Servers []Server `json:"servers,omitempty"`
DefaultServer []KeywordArg `json:"defaultServer,omitempty"`
BodyDigest string `json:"bodyDigest"`
CommentsDigest string `json:"commentsDigest"`
RecordDigest string `json:"recordDigest"`
TextDigest string `json:"textDigest"`
Body []string `json:"-"`
Comments []string `json:"-"`
ContentKnown bool `json:"-"`
}
Backend is the record a generator macro declared alongside the backend section text it emitted.
func (*Backend) EqualContent ¶
EqualContent reports whether both backends carry the same text description: the body, comment and record digests, the body and comment lines, and whether the content is known. TextDigest is left to the caller, since it changes with every render that re-emits the section.
func (*Backend) EqualRecord ¶
EqualRecord reports whether both backends declare the same record: every field that describes the backend itself rather than its text. The digests, the body and comment lines and ContentKnown describe the text and are compared by EqualContent. A plan with thousands of backends compares every one per deployment, so this is field by field rather than reflective.
type BackendHandle ¶
type BackendHandle struct {
// contains filtered or unexported fields
}
BackendHandle proves one exact backend record.
type BackendSource ¶
type BackendSource interface {
// Token identifies the source's state; the snapshot built from it keeps
// the token and offers it to the next transition. It must be comparable
// (a pointer, or nil), since snapshots compare tokens with ==.
Token() any
// ChangedSince lists every name whose entry may differ from the state
// token identifies. ok is false when the source cannot tell, and the
// transition then compares every backend.
ChangedSince(token any) (names []string, ok bool)
// Get returns the backend by name; ContentKnown is true on every backend
// the source returns.
Get(name string) (Backend, bool)
Len() int
// Walk visits every backend in an unspecified order.
Walk(func(name string, backend Backend) error) error
}
BackendSource hands a document transition the plan's backends by name, so a transition from a snapshot built from an earlier state of the same source compares only the names that changed in between instead of every backend.
type CRTList ¶
type CRTList struct {
Path string `json:"path"`
Entries []CRTListEntry `json:"entries,omitempty"`
}
CRTList is the entry list of one crt-list file, declared by the generator that emitted the file.
type CRTListEntry ¶
type CRTListEntry struct {
Cert string `json:"cert"`
Options []KeywordArg `json:"options,omitempty"`
SNIFilters []string `json:"sniFilters,omitempty"`
}
CRTListEntry is one crt-list line: the certificate, its ssl options and the SNI filters that select it.
type CRTListHandle ¶
type CRTListHandle struct {
// contains filtered or unexported fields
}
CRTListHandle proves one exact CRT-list record.
type Changes ¶
type Changes struct {
Sections []SequenceChange[Section]
Backends []NamedChange[Backend]
Profiles []NamedChange[Profile]
Maps []NamedChange[Map]
CRTLists []NamedChange[CRTList]
Files []FileChange
}
Changes is the exact changed-record set carried by a Delta.
type CurrentConfig ¶
type CurrentConfig struct {
ServerIndex map[string]map[string]ServerAddr `json:"serverIndex"`
}
CurrentConfig is the client-native-free view of the running configuration that templates read as `currentConfig`.
type Delta ¶
type Delta struct {
// contains filtered or unexported fields
}
Delta is an authenticated transition between exact plan roots.
func (*Delta) RequiresFullValidation ¶
RequiresFullValidation reports structural changes not safe for local validation.
func (*Delta) SectionChanges ¶
func (d *Delta) SectionChanges() ([]SequenceChange[Section], error)
SectionChanges validates the complete delta and returns detached section changes.
func (*Delta) ValidateAuthentication ¶
ValidateAuthentication verifies the exact transition and every changed record.
type Entry ¶
Entry is one map-file line: the key and the rest of the line.
func ParseMapEntries ¶
ParseMapEntries splits rendered map-file content into entries: the first field is the key, the rest of the line the value. Blank and comment lines are dropped; duplicate keys are kept in order, because HAProxy map lookups are a multiset and a delta over them must see every occurrence.
This reads HAPTIC's own output format, not HAProxy configuration.
type File ¶
type File struct {
Path string `json:"path"`
Kind string `json:"kind"`
ReloadOnChange bool `json:"reloadOnChange"`
Digest string `json:"digest"`
Size int64 `json:"size"`
Content string `json:"-"`
ContentKnown bool `json:"-"`
}
File is one file the render produced.
type FileChange ¶
type FileChange struct {
Index int
Before *FileRecord
After *FileRecord
}
FileChange is one exact file transition. Nil means absent.
type FileDescriptor ¶
FileDescriptor is plan-file metadata available without materializing content.
type FileGapHandle ¶
type FileGapHandle struct {
// contains filtered or unexported fields
}
FileGapHandle proves one exact insertion gap in the file sequence.
type FileHandle ¶
type FileHandle struct {
// contains filtered or unexported fields
}
FileHandle proves one exact file and its sequence position.
type FileRecord ¶
type FileRecord struct {
// contains filtered or unexported fields
}
FileRecord is an authenticated immutable plan-file value.
func (*FileRecord) ConfigDocument ¶
func (r *FileRecord) ConfigDocument() (rendercontent.Document, bool, error)
ConfigDocument returns the retained config document when this record has one.
func (*FileRecord) Descriptor ¶
func (r *FileRecord) Descriptor() (FileDescriptor, error)
Descriptor returns file identity and size without materializing its content.
func (*FileRecord) LegacyCopy ¶
func (r *FileRecord) LegacyCopy() (File, error)
LegacyCopy materializes a detached compatibility file.
type KeywordArg ¶
KeywordArg is a server or default-server keyword with its arguments, structured so no consumer has to scan the emitted line.
type Map ¶
type Map struct {
Path string `json:"path"`
Ordered bool `json:"ordered"`
Entries []Entry `json:"entries,omitempty"`
}
Map is the entry list of one map file, derived from its rendered content.
type MapHandle ¶
type MapHandle struct {
// contains filtered or unexported fields
}
MapHandle proves one exact map record.
type NamedChange ¶
NamedChange is one keyed record transition. Nil means absent.
type ParsedMapEntries ¶
type ParsedMapEntries struct {
Content string
Entries []Entry
// contains filtered or unexported fields
}
ParsedMapEntries is a map file's entries with the text they came from, so the next version of the text parses only the lines that changed. Every entry's key and value are substrings of Content and of nothing older: a carried entry is re-sliced into the new text, or the text of every version whose lines survive would stay alive behind it.
func ParseMapEntriesIndexed ¶
func ParseMapEntriesIndexed(content string) ParsedMapEntries
ParseMapEntriesIndexed is ParseMapEntries keeping what Reparse needs.
func (ParsedMapEntries) Reparse ¶
func (p ParsedMapEntries) Reparse(content string) ParsedMapEntries
Reparse parses content, reusing the entries of every line that is unchanged at the head and at the tail of the previous text. An entry depends only on its own line, so only the lines between the two are parsed again.
type Plan ¶
type Plan struct {
SchemaVersion int `json:"schemaVersion"`
ID string `json:"id"`
Sections []Section `json:"sections"`
Backends map[string]Backend `json:"backends"`
Profiles map[string]Profile `json:"profiles"`
Maps map[string]Map `json:"maps"`
CRTLists map[string]CRTList `json:"crtLists,omitempty"`
Files []File `json:"files"`
}
Plan is the immutable structure of one render.
func (*Plan) Canonical ¶
Canonical returns the deterministic JSON encoding of the plan with the ID cleared, so the ID can be a digest over it. encoding/json sorts map keys and keeps struct fields in declaration order.
func (*Plan) ComputeID ¶
func (p *Plan) ComputeID()
ComputeID sets the plan ID to the digest of its canonical encoding.
func (*Plan) CurrentConfig ¶
func (p *Plan) CurrentConfig() CurrentConfig
CurrentConfig projects the plan's backend servers into the shape templates read as `currentConfig`.
type Profile ¶
type Profile struct {
Name string `json:"name"`
BodyDigest string `json:"bodyDigest"`
HasRules bool `json:"hasRules,omitempty"`
}
Profile is a named defaults section shared by backends.
type ProfileHandle ¶
type ProfileHandle struct {
// contains filtered or unexported fields
}
ProfileHandle proves one exact profile record.
type Section ¶
type Section struct {
Kind string `json:"kind"`
Name string `json:"name"`
TextDigest string `json:"textDigest"`
Length int `json:"length"`
Text string `json:"-"`
TextKnown bool `json:"-"`
}
Section is one contiguous run of haproxy.cfg. The sections of a plan partition the file: concatenating their text reproduces it byte for byte.
type SectionGapHandle ¶
type SectionGapHandle struct {
// contains filtered or unexported fields
}
SectionGapHandle proves one exact insertion gap in the section sequence.
type SectionHandle ¶
type SectionHandle struct {
// contains filtered or unexported fields
}
SectionHandle proves one exact section and its emission position.
type SequenceChange ¶
SequenceChange is one ordered record transition. Nil means absent.
type Server ¶
type Server struct {
Name string `json:"name"`
Address string `json:"address"`
Port int `json:"port"`
Weight *int `json:"weight,omitempty"` // nil: no weight keyword; 0 is a real weight
Disabled bool `json:"disabled,omitempty"`
GUID string `json:"guid,omitempty"`
Comment string `json:"comment,omitempty"`
Extra []KeywordArg `json:"extra,omitempty"`
}
Server is one server line, declared as data.
type ServerAddr ¶
ServerAddr is one server's address as templates see it. Port is a pointer because a server line may omit it and templates dereference it.
type Snapshot ¶
type Snapshot struct {
// contains filtered or unexported fields
}
Snapshot is an authenticated immutable final render plan.
func NewSnapshot ¶
NewSnapshot deeply owns plan and reuses exact roots from previous.
func NewSnapshotWithConfigDocument ¶
func NewSnapshotWithConfigDocument( authority *Authority, plan *Plan, document rendercontent.Document, previous *Snapshot, ) (*Snapshot, error)
NewSnapshotWithConfigDocument owns plan while retaining config as a document.
func (*Snapshot) BackendHandle ¶
func (s *Snapshot) BackendHandle(name string) (*BackendHandle, bool, error)
BackendHandle returns a proof for name when present.
func (*Snapshot) BackendNamed ¶
BackendNamed returns a detached exact backend by name.
func (*Snapshot) CRTListHandle ¶
func (s *Snapshot) CRTListHandle(path string) (*CRTListHandle, bool, error)
CRTListHandle returns a proof for path when present.
func (*Snapshot) ExactEqual ¶
ExactEqual compares complete local plan content; IDs never authorize equality.
func (*Snapshot) FileGapHandle ¶
func (s *Snapshot) FileGapHandle(index int) (*FileGapHandle, error)
FileGapHandle returns a proof for the file insertion gap at index.
func (*Snapshot) FileHandle ¶
func (s *Snapshot) FileHandle(index int) (*FileHandle, error)
FileHandle returns a proof for the file at index.
func (*Snapshot) LegacyCopy ¶
LegacyCopy materializes a fully detached Plan compatibility value.
func (*Snapshot) MarshalJSON ¶
MarshalJSON preserves the canonical fragments and falls back when their order is unproven.
func (*Snapshot) ProfileHandle ¶
func (s *Snapshot) ProfileHandle(name string) (*ProfileHandle, bool, error)
ProfileHandle returns a proof for name when present.
func (*Snapshot) ProfileNamed ¶
ProfileNamed returns a detached exact profile by name.
func (*Snapshot) SectionGapHandle ¶
func (s *Snapshot) SectionGapHandle(index int) (*SectionGapHandle, error)
SectionGapHandle returns a proof for the section insertion gap at index.
func (*Snapshot) SectionHandle ¶
func (s *Snapshot) SectionHandle(index int) (*SectionHandle, error)
SectionHandle returns a proof for the section at index.
func (*Snapshot) SectionsCopy ¶
SectionsCopy returns detached ordered section metadata without materializing config.
func (*Snapshot) SharedPlan ¶
SharedPlan is the snapshot's Plan as a read-only view, built once per snapshot: its records alias the sealed entries, which every reader of a plan must leave alone. A caller that changes a plan takes LegacyCopy. Materialising a detached copy per deployment deep-copied every backend before any pod was touched.
func (*Snapshot) ValidateAuthentication ¶
ValidateAuthentication verifies the private root in constant time.
type Transaction ¶
type Transaction struct {
// contains filtered or unexported fields
}
Transaction atomically path-copies changes from one exact plan root.
func BeginTransaction ¶
func BeginTransaction(authority *Authority, base *Snapshot) (*Transaction, error)
BeginTransaction starts an atomic edit against base.
func (*Transaction) Commit ¶
func (t *Transaction) Commit() (*Snapshot, *Delta, error)
Commit seals the next snapshot and its exact base-to-next proof.
func (*Transaction) DeleteBackend ¶
func (t *Transaction) DeleteBackend(expected *BackendHandle) error
DeleteBackend removes an exact backend and requires full output validation.
func (*Transaction) DeleteFile ¶
func (t *Transaction) DeleteFile(expected *FileHandle) error
DeleteFile removes an exact file and requires full output validation.
func (*Transaction) DeleteMap ¶
func (t *Transaction) DeleteMap(expected *MapHandle) error
DeleteMap removes an exact map and requires full output validation.
func (*Transaction) DeleteProfile ¶
func (t *Transaction) DeleteProfile(expected *ProfileHandle) error
DeleteProfile removes an exact profile and requires full output validation.
func (*Transaction) DeleteSection ¶
func (t *Transaction) DeleteSection(expected *SectionHandle) error
DeleteSection removes an exact section and requires full output validation.
func (*Transaction) InsertBackend ¶
func (t *Transaction) InsertBackend(name string, backend Backend) error
InsertBackend inserts a new keyed backend and requires full output validation.
func (*Transaction) InsertFile ¶
func (t *Transaction) InsertFile(expected *FileGapHandle, file File) error
InsertFile inserts a file at an exact gap and requires full output validation.
func (*Transaction) InsertMap ¶
func (t *Transaction) InsertMap(path string, value Map) error
InsertMap inserts a new keyed map and requires full output validation.
func (*Transaction) InsertProfile ¶
func (t *Transaction) InsertProfile(name string, profile Profile) error
InsertProfile inserts a new keyed profile and requires full output validation.
func (*Transaction) InsertSection ¶
func (t *Transaction) InsertSection(expected *SectionGapHandle, section Section) error
InsertSection inserts a section at an exact gap and requires full output validation.
func (*Transaction) ReplaceBackend ¶
func (t *Transaction) ReplaceBackend(expected *BackendHandle, backend Backend) error
ReplaceBackend changes only the exact backend proven by expected.
func (*Transaction) ReplaceCRTList ¶
func (t *Transaction) ReplaceCRTList(expected *CRTListHandle, value CRTList) error
ReplaceCRTList changes only the exact CRT-list proven by expected.
func (*Transaction) ReplaceConfigFileDocument ¶
func (t *Transaction) ReplaceConfigFileDocument( expected *FileHandle, document rendercontent.Document, ) error
ReplaceConfigFileDocument replaces the config file without materializing its content.
func (*Transaction) ReplaceFile ¶
func (t *Transaction) ReplaceFile(expected *FileHandle, file File) error
ReplaceFile changes only the exact file proven by expected.
func (*Transaction) ReplaceMap ¶
func (t *Transaction) ReplaceMap(expected *MapHandle, value Map) error
ReplaceMap changes only the exact map proven by expected.
func (*Transaction) ReplaceProfile ¶
func (t *Transaction) ReplaceProfile(expected *ProfileHandle, profile Profile) error
ReplaceProfile changes only the exact profile proven by expected.
func (*Transaction) ReplaceSection ¶
func (t *Transaction) ReplaceSection(expected *SectionHandle, section Section) error
ReplaceSection changes only the exact section proven by expected.