Documentation
¶
Index ¶
- Constants
- Variables
- func All[T any](c *Config) ([]*T, error)
- func As[T any](entity any) (*T, error)
- func Decode(c *Config, target any) error
- func DiagnosticPieces(diagnostics xclerrors.Diagnostics, width int) []highlight.Piece
- func EncodeEntity(entity any, options ...EncodeOption) ([]byte, error)
- func Find[T any](c *Config, address string) (*T, error)
- func FindByType[T any](c *Config, path ...string) ([]*T, error)
- func FindOne[T any](c *Config, path ...string) (*T, error)
- func HashString(in string) string
- func ReadFileLocation(filename string, startLine, startCol, endLine, endCol int) (string, error)
- type Config
- func (c *Config) All[T any]() ([]*T, error)
- func (c *Config) Apply(paths ...string) error
- func (c *Config) ApplyContext(ctx context.Context, paths ...string) error
- func (c *Config) Decode(target any) error
- func (c *Config) Destroy() error
- func (c *Config) DestroyContext(ctx context.Context) error
- func (c *Config) Diff(paths []string, options ...diff.Option) (*diff.Diff, error)
- func (c *Config) DiffContext(ctx context.Context, paths []string, options ...diff.Option) (*diff.Diff, error)
- func (c *Config) EncodeEntityRecord(data []byte, options ...EncodeOption) ([]byte, error)
- func (c *Config) EncodeSavedEntity(data []byte, options ...EncodeOption) ([]byte, error)
- func (c *Config) Entities() []any
- func (c *Config) EntityCount() int
- func (c *Config) Find[T any](address string) (*T, error)
- func (c *Config) FindByType[T any](path ...string) ([]*T, error)
- func (c *Config) FindEntitiesByType(path ...string) ([]any, error)
- func (c *Config) FindOne[T any](path ...string) (*T, error)
- func (c *Config) FindOneEntity(path ...string) (any, error)
- func (c *Config) FindResource(path string) (any, error)
- func (c *Config) GetResources() []anydeprecated
- func (c *Config) Load() error
- func (c *Config) LoadContext(ctx context.Context) error
- func (c *Config) Outputs() map[string]any
- func (c *Config) ResourceCount() intdeprecated
- func (c *Config) Validate(paths ...string) error
- func (c *Config) ValidateContext(ctx context.Context, paths ...string) error
- type ConfigOption
- func WithEventBufferSize(size int) ConfigOption
- func WithEventData(level EventDataLevel) ConfigOption
- func WithEventHandler(handler EventHandler) ConfigOption
- func WithEventMask(m mask.Masker) ConfigOption
- func WithNoEventMask() ConfigOption
- func WithRegistry(r registry.Registry) ConfigOption
- func WithStateMask(m mask.Masker) ConfigOption
- func WithStatePath(dir string) ConfigOption
- func WithStateStore(ss state.StateStore) ConfigOption
- func WithVariables(vars map[string]any) ConfigOption
- type EncodeOption
- type Event
- type EventDataLevel
- type EventHandler
- type FunctionNameClashError
- type InvalidDecodeTargetError
- type InvalidFunctionError
- type InvalidSavedDataError
- type InvalidThemeError
- type InvalidTypeError
- type MaskNotReversibleError
- type NotAnEntityError
- type NotEncodableError
- type NotFoundError
- type NotRegisteredError
- type NotTypeableError
- type NotUniqueError
- type PluginInstallError
- type PluginLoadError
- type TypeFormError
- type TypeMismatchError
- type TypeNameClashError
- type UnknownTypeError
- type UnrecoverableError
- type UnregisteredTypeError
Constants ¶
const ( // EventDataNone carries no resource data on any event. It is the default. EventDataNone = events.DataNone // EventDataRaw carries the resource as it was before the provider was // called, on every lifecycle event. EventDataRaw = events.DataRaw // EventDataProcessed carries, on a success event, the resource as xcl // records it in state, including the values the provider filled in. A // receiver reads it as a typed entity with Event.Entity, or turns it // straight back into configuration text with Config.EncodeSavedEntity. // Sensitive values in it are masked by the // event masker, so it matches the state record only where both mask // alike. EventDataProcessed = events.DataProcessed )
const DefaultEventBufferSize = 1024
DefaultEventBufferSize is the number of undelivered events a Validate, Apply or Destroy holds when WithEventBufferSize is not used
const LineEnding = "\n"
Variables ¶
var ( // ErrNotFound means no entity is declared at the address given. It is // distinct from plugins.ErrNotFound, which means the real infrastructure // behind a declared entity has gone missing. ErrNotFound = xclerrors.ErrNotFound // ErrUnknownType means the leading segment of a query is not a known kind. ErrUnknownType = xclerrors.ErrUnknownType // ErrNotTypeable means the query matches entities of more than one Go // type, so the result cannot be typed. ErrNotTypeable = xclerrors.ErrNotTypeable // ErrNotRegistered means a Go type has no registered name to derive an // address from, which is always so for a plugin provided type. ErrNotRegistered = xclerrors.ErrNotRegistered // ErrTypeMismatch means an entity is not of the Go type asked for. ErrTypeMismatch = xclerrors.ErrTypeMismatch // ErrNotAnEntity means a Go type is a block nested inside another // declaration and so has no address of its own. ErrNotAnEntity = xclerrors.ErrNotAnEntity // ErrNotUnique means a query expecting exactly one entity matched more // than one. The detail reports how many. ErrNotUnique = xclerrors.ErrNotUnique // ErrInvalidDecodeTarget means Decode was not given a non-nil pointer to a // struct, so there was nothing it could fill. ErrInvalidDecodeTarget = xclerrors.ErrInvalidDecodeTarget )
The errors a lookup against a configuration can return. Each is matched by identity with errors.Is, and each is wrapped by the detail type below it, recovered with errors.As.
They are re-exported from the project's errors package so that matching one needs no import named errors beside the standard library's.
ErrNotFound and ErrNotUnique are ordinary outcomes to handle. The other five mean the question itself had no answer, and ErrInvalidDecodeTarget means Decode was given nothing it could fill.
var ( // ErrPluginNotFound means the plugin's release, or its build for the // current platform, does not exist, or the repository is private and no // token was given. ErrPluginNotFound = xclerrors.ErrPluginNotFound // ErrPluginVerification means a downloaded or cached plugin failed // verification: no checksums, a checksum mismatch, or a missing or // untrusted signature when trusted keys were given. ErrPluginVerification = xclerrors.ErrPluginVerification )
The errors below name the ways a remote registry, such as the GitHub registry, can fail to install a plugin. They reach the caller inside a PluginLoadError naming the plugin, check for them with errors.Is, and recover the repository, version and platform with errors.As and PluginInstallError.
var ( // ErrUnregisteredType means saved data names a type the registry cannot // create. The UnregisteredTypeError detail names the type. A plugin's // types resolve only once the registry has loaded. ErrUnregisteredType = xclerrors.ErrUnregisteredType // ErrInvalidSavedData means the data given is not one saved entity // record. The InvalidSavedDataError detail names the record where it was // readable enough to name itself. ErrInvalidSavedData = xclerrors.ErrInvalidSavedData // ErrNotEncodable means a value cannot be written as configuration, // because it is not an entity, it is a builtin such as a variable, output // or module, or it holds a value that has no configuration form. ErrNotEncodable = xclerrors.ErrNotEncodable // ErrInvalidTheme means a colour theme given to highlight.NewANSI // cannot be read or is not a valid VS Code colour theme. The // InvalidThemeError detail names the theme and what was wrong with it. ErrInvalidTheme = xclerrors.ErrInvalidTheme )
The errors below name every way turning an entity, or an entity's saved data, into configuration text can fail. Check for them with errors.Is, and recover the detail carried alongside each with errors.As.
var ( // ErrUnrecoverable means a masked value cannot be turned back into its // real value: its masker is one way, it was masked by a different masker, // or it does not open, for example under a different key. Loading state // that holds such a value fails with it, rather than losing the secret. ErrUnrecoverable = xclerrors.ErrUnrecoverable // ErrMaskNotReversible means a masker that cannot recover the values it // masks was given to WithStateMask. The MaskNotReversibleError detail // names the masker. ErrMaskNotReversible = xclerrors.ErrMaskNotReversible )
The errors below name the ways masking a sensitive value can fail. Check for them with errors.Is, and recover the detail with errors.As.
var ErrEmptyConfiguration = parser.ErrEmptyConfiguration
ErrEmptyConfiguration is returned by Apply when the configuration declares no blocks. Nothing is destroyed, created, changed or saved: use Destroy to remove everything. Check for it with errors.Is.
var ErrPluginLoad = xclerrors.ErrPluginLoad
ErrPluginLoad is returned by the first Validate, Apply or Destroy when a registered plugin cannot be loaded, plugins load when first needed rather than when registered. Check for it with errors.Is, the PluginLoadError detail names the plugin.
Functions ¶
func All ¶
All returns every entity of the Go type T, without naming it as a string.
The addressing is worked out from how T was registered, so All[Container] returns what FindByType[Container]("resource", "container") returns for a type registered as ("resource", "container"), and what FindByType[Container]("container") returns for one registered as ("container") alone.
A plugin provides a schema and no Go type, so a plugin backed entity cannot be matched this way. Asking for one returns an error wrapping ErrNotRegistered, naming the kind lookup as the form that does work.
func As ¶
As converts an entity, typically one taken from an untyped enumeration, into a caller's Go type.
An entity of a declared or plugin type is handed back as a copy of its plain struct, labels and Meta filled; changing the copy leaves the configuration as it is, as only configuration and a provider's results set an entity. An entity that already is a *T, such as a builtin types.Output, is returned as it stands.
Where the entity's own Go type says it cannot be a T, the conversion is refused. The copy underneath is a JSON round trip that drops unknown fields and zeroes absent ones, so without that refusal converting one entity into an unrelated type would quietly yield a value with most of its fields unset.
func Decode ¶
Decode fills target from the entities the configuration declares, in one call, so an application can gather its configuration into a struct of its own rather than asking for each type separately.
target must be a non-nil pointer to a struct. Each of its exported fields is matched by its type alone; no tags are read and field names play no part:
- A []*T field, where T is a registered type or a builtin such as types.Output, receives every entity of T, exactly as All returns them: in declaration order, disabled entities included, each a copy, so changing one leaves the configuration as it is. None declared gives an empty, non-nil slice.
- A *T field, where T is a registered type, receives the one entity of T. None declared sets it to nil. More than one makes the call fail with the error FindOne returns for the same type, matching ErrNotUnique.
- Every other field, including a []*T or *T whose T the registry cannot reach, such as an unregistered or plugin provided type, keeps its value. Nested structs are not entered.
A target that is not a non-nil pointer to a struct returns an error wrapping ErrInvalidDecodeTarget. On any error no field is assigned, so target is never left partly filled. Before Apply the call succeeds, leaving every slice empty and every pointer nil. c must not be nil.
Decode is not generic, so unlike the generic lookups its method form is available on every supported Go version.
func DiagnosticPieces ¶ added in v0.7.0
func DiagnosticPieces(diagnostics xclerrors.Diagnostics, width int) []highlight.Piece
DiagnosticPieces lays diagnostics out as a report for a person to read, as labelled pieces for a renderer: highlight.Text for plain text, highlight.ANSI for a terminal, or any other highlight.Renderer.
Each diagnostic is written as its severity and summary, where it is — the file, the line, and the block and field it is in — the lines of source around it, and its detail:
Error: Unsupported argument
on main.xcl line 2, in agent.claude:
2 | modls = ["opus"]
An argument named "modls" is not expected here.
The severity is labelled highlight.ScopeError or highlight.ScopeWarning, and so is the source at fault; the rest of the source is labelled as configuration, as highlight.Pieces labels it. The source is the lines the diagnostic took when it was made, so laying it out never reads a file.
The detail is wrapped at width columns; a width of 0 leaves it unwrapped. Source lines are never wrapped.
func EncodeEntity ¶
func EncodeEntity(entity any, options ...EncodeOption) ([]byte, error)
EncodeEntity returns entity as configuration text in xcl's own syntax, formatted and ready to print or write to a .xcl file.
entity is one entity, such as one returned by Find, FindByType, All or Entities after Apply. The text holds exactly one block: <type> "<subtype>" "<name>" for an entity with a subtype, i.e. resource "container" "nics", and <type> "<name>" for one without. Convert several entities by calling this once for each.
Fields a provider filled in are left out unless IncludeComputed is given, so the text reads back to the same configured values. Optional attributes at their zero value, and attributes that are not set, are left out unless IncludeEmpty is given. Values are written as the literals they resolved to, not as the expressions the original configuration used, unless ShowReferences is given. The text is plain, with no colour or markup; to colour it, render its pieces, such as highlight.ANSI.Render(highlight.Pieces(text)).
It fails with ErrNotEncodable when entity is not an entity, when it is a builtin such as a variable, output or module, or when it holds a value that has no configuration form. A failure returns no text.
func Find ¶
Find returns the entity declared at address, as T.
The address is complete: resource.container.mine, variable.region, module.db.output.connection. A bare name is not an address and is not inferred. A module relative address, one that is not normalised, and one carrying a trailing attribute suffix all resolve to the same entity.
An address that matches nothing returns an error wrapping ErrNotFound. An entity that is not a T returns one wrapping ErrTypeMismatch, and never a value with some of its fields unset.
An output address returns the types.Output entity like any other entity, and its Value holds the published value. Asking for an output as any other type, a plain string for instance, returns an error wrapping ErrTypeMismatch; Config.Outputs returns every published value at once.
func FindByType ¶
FindByType returns every entity whose address begins with the segments given, as T.
The segments are matched positionally from the root, exactly as they appear in an address: FindByType[Container](c, "resource", "container") for an entity declared resource "container" "nics", and FindByType[Container](c, "container") for one declared container "nics". Segment one is always the type, so a subtype on its own matches nothing and says so rather than matching in the wrong position.
At least one segment is required; the no-segment form is All.
A well formed query that matches nothing returns an empty result and a nil error. A query that cannot be answered returns an error: one wrapping ErrUnknownType where the leading segment is not a type, and one wrapping ErrNotTypeable where the segments span more than one Go type, as a type that takes a subtype does when it is given alone.
func FindOne ¶
FindOne returns the single entity matching the segments given.
It is for the entity a configuration is expected to declare exactly one of, and returns it directly rather than a collection to index into. Finding none returns an error wrapping ErrNotFound, and finding more than one returns one wrapping ErrNotUnique, whose detail reports how many were found.
func HashString ¶
HashString creates an MD5 hash of the given string
Types ¶
type Config ¶
type Config struct {
// contains filtered or unexported fields
}
Config defines the stack config It orchestrates high-level operations (Apply, Validate, Diff, Destroy) and manages the current state
func NewConfig ¶
func NewConfig(opts ...ConfigOption) (*Config, error)
NewConfig creates a new Config with functional options If no options are provided, creates a minimal config with only the builtin resource types and no state. The options are applied in order, and the first one to fail stops NewConfig and its error is returned.
Options may be given in any order: NewConfig collects every option first, then builds the Config's own catalog from the registries added with WithRegistry, reading each registry's Types and Functions in the order the registries were given. A declared Go type that duplicates another, in one registry or across two, is returned as a *TypeNameClashError naming both and their registries, one with a builtin name as a *TypeNameClashError naming "builtin", and one that uses its type keyword in both forms as a *TypeFormError. An application function named like a builtin or like another application function is returned as a *FunctionNameClashError, and one whose signature cannot be called from configuration as an *InvalidFunctionError. Plugins are not loaded here, they load on the first operation that needs them.
func (*Config) All ¶
All returns every entity of the Go type T, without naming it as a string.
See the package level All for the full contract.
func (*Config) Apply ¶
Apply parses config from paths, loads existing state, and applies changes. Resources that were applied before but are no longer in the configuration are destroyed first, children before parents, before anything is created or changed. Plugins are then executed for each resource in dependency order and the resulting state is saved. When a provider call fails, the progress made so far is saved before the error is returned, so the next apply resumes from it. A removed resource whose destroy fails stops the apply before anything is created or changed, and is kept as destroy_failed for the next apply to retry first. Nothing is saved when the configuration does not parse or validate, or when it declares no blocks, which returns ErrEmptyConfiguration: use Destroy to remove everything.
func (*Config) ApplyContext ¶ added in v0.4.0
ApplyContext is Apply under the caller's context, so the caller can stop an apply that is in progress. Cancelling ctx starts no further provider call: a call already running finishes, the progress made is saved to the state store exactly as it is after a failed provider call, and ApplyContext returns an error that wraps context.Canceled, or context.DeadlineExceeded when a deadline passed. A ctx that is already cancelled stops the apply before any provider is called. The next apply resumes from the saved progress.
func (*Config) Decode ¶
Decode fills target from the entities the configuration declares. See the package level Decode for the full contract.
func (*Config) Destroy ¶
Destroy removes every resource in the saved state, or in the in-memory state when no state store is configured. It needs no configuration: resources are destroyed children first, in the reverse of the order they were created in, using the parents each resource recorded when it was applied. Variables, outputs, modules, disabled blocks and registered types never reach a provider.
The state is saved after each resource, so an interrupted destroy resumes from where it stopped. A resource that fails to be destroyed stays in the state as destroy_failed, together with everything it depends on, and is named in the returned error; calling Destroy again retries it. When nothing has been saved Destroy succeeds and writes nothing.
func (*Config) DestroyContext ¶ added in v0.4.0
DestroyContext is Destroy under the caller's context, so the caller can stop a destroy that is in progress. Cancelling ctx starts no further provider call: a destroy already running finishes and is saved, the resources not yet reached stay in the state, and DestroyContext returns an error that wraps context.Canceled, or context.DeadlineExceeded when a deadline passed. Calling Destroy again removes what remains.
func (*Config) Diff ¶
Diff reports what Apply would do with the configuration discovered from paths, without doing any of it: which resources an apply would create, update, replace or delete, and how many it would leave unchanged.
Diff takes the same paths as Apply and resolves the configuration the same way, so it fails in the same cases: no paths, a configuration that does not parse or validate, one that declares no blocks (ErrEmptyConfiguration), or a saved state that cannot be loaded. It compares against the state Apply would use: the state loaded from the StateStore, or an empty state when there is none.
Every resource in the saved state that is still configured is read and compared through its provider, exactly as Apply does, so a resource changed outside xcl is reported as updated and one that no longer exists as created. A provider error while reading or comparing fails the diff with an error naming the resource.
Diff never creates, updates or destroys a resource, never saves state, and leaves what Entities returns untouched. It runs as the diff operation, with the same events and logging as Apply. Sensitive values are left out of the result unless diff.RevealSensitive is given.
func (*Config) DiffContext ¶ added in v0.4.0
func (c *Config) DiffContext(ctx context.Context, paths []string, options ...diff.Option) (*diff.Diff, error)
DiffContext is Diff under the caller's context, so the caller can stop a diff that is in progress. Cancelling ctx starts no further provider read or comparison; a call already running finishes, and DiffContext returns no diff and an error that wraps context.Canceled, or context.DeadlineExceeded when a deadline passed. A ctx that is already cancelled stops the diff before any provider is called.
func (*Config) EncodeEntityRecord ¶ added in v0.11.0
func (c *Config) EncodeEntityRecord(data []byte, options ...EncodeOption) ([]byte, error)
EncodeEntityRecord returns the configuration text for an entity's JSON record, in the shape a lookup returns it, as encoding/json writes an entity such as one returned by Find, FindByType or Entities, and possibly edited since. The text is identical to what EncodeEntity returns for the same entity with the same options.
A lookup's record holds types.SensitiveMarker in place of every sensitive value, set or not, and leaves out every list or map that is empty. So what the record lost is taken from this Config's own copy of the entity its meta.id names, and the text is what EncodeEntity writes for that entity: a sensitive value still holding the marker is written as the marker when it is set, as its configured value with RevealSensitive, and not at all when it was never set, and an empty list or map the record leaves out is written as the entity holds it. A sensitive value the record holds for real, such as one edited since the lookup or set in a record built by hand, is shown as it is, as the marker unless RevealSensitive is given. A record whose meta.id is missing or names no entity of this Config is not filled, and its marker values stay the marker.
The record's type is resolved through the Config's own types and plugins, and plugins are loaded if no operation has yet, as for EncodeSavedEntity.
It fails with ErrUnregisteredType when the Config does not know the type the record names, with ErrInvalidSavedData when the data is not one entity record, with ErrPluginLoad when a plugin fails to load, and with ErrNotEncodable on the same terms as EncodeEntity. A failure returns no text.
func (*Config) EncodeSavedEntity ¶
func (c *Config) EncodeSavedEntity(data []byte, options ...EncodeOption) ([]byte, error)
EncodeSavedEntity returns the configuration text for one entity's saved data, exactly as state stores it and as events carry it at EventDataProcessed. The text is identical to what EncodeEntity returns for the same entity. A sensitive value masked in state or in event data, see WithStateMask and WithEventMask, is shown as types.SensitiveMarker, never as ciphertext or a hash; a receiver that needs the real value opens it with mask.Unmask.
The record's type is resolved through the Config's own types and plugins. A plugin's types resolve only once the plugins have loaded, so this loads them if no operation has yet. Loading happens once per Config and is cached, so calling this before any operation works, and calling it after costs nothing.
It fails with ErrUnregisteredType when the Config does not know the type the record names, with ErrInvalidSavedData when the data is not one saved entity record, with ErrPluginLoad when a plugin fails to load, and with ErrNotEncodable on the same terms as EncodeEntity. A failure returns no text.
func (*Config) EntityCount ¶
ResourceCount returns number of resources in current state
func (*Config) Find ¶
Find returns the entity declared at address, as T.
See the package level Find for the full contract.
func (*Config) FindByType ¶
FindByType returns every entity whose address begins with the segments given, as T.
See the package level FindByType for the full contract.
func (*Config) FindEntitiesByType ¶ added in v0.4.0
FindEntitiesByType returns every entity of the type the segments name, exactly as FindByType does, but without a Go type to convert to: each entity is returned as the Config stores it. It is for a host that has no Go type for what it is asking about, such as a language binding driving the core, or a program reading a plugin's entities generically.
The segments follow the rules of FindByType, with the same errors: the first names a type and the second, where the type takes one, its subtype; at least one segment is required; a leading segment that is not a type returns an error wrapping ErrUnknownType, and segments that span more than one type, as a type that takes a subtype does on its own, return one wrapping ErrNotTypeable. A well formed query that matches nothing returns an empty result and a nil error.
func (*Config) FindOne ¶
FindOne returns the single entity matching the segments given.
See the package level FindOne for the full contract.
func (*Config) FindOneEntity ¶ added in v0.4.0
FindOneEntity returns the single entity of the type the segments name, exactly as FindOne does, but without a Go type to convert to: the entity is returned as the Config stores it. The segments and their errors are those of FindEntitiesByType. Finding none returns an error wrapping ErrNotFound, and finding more than one returns one wrapping ErrNotUnique, whose detail reports how many were found.
func (*Config) FindResource ¶
FindResource finds a resource in current state by FQRN path
func (*Config) GetResources
deprecated
GetResources returns every entity the configuration declares.
Deprecated: use Entities. The configuration declares more than resources — variables, published values and modules are entities too — and the name said otherwise. This returns exactly what Entities returns.
func (*Config) Load ¶
Load reads the saved state into the Config without applying or destroying anything, so Entities, Find, FindByType and the other lookups answer from what was last saved. It needs no configuration and calls no provider. A program that applies in one run and reports in another, i.e. a status command, calls it before looking anything up.
Plugins are loaded first, a saved plugin type is read back into its Go type through its plugin's schema. When nothing has been saved Load succeeds and the Config holds nothing. Without a state store there is nothing to read, Load succeeds and keeps what the Config already holds.
func (*Config) LoadContext ¶ added in v0.4.0
LoadContext is Load under the caller's context. Load calls no provider, so ctx is observed only before the state is read: a ctx that is already cancelled returns an error wrapping context.Canceled, or context.DeadlineExceeded when a deadline passed, and leaves what the Config holds untouched.
func (*Config) Outputs ¶
Outputs returns every value the configuration publishes, keyed by address.
There is one entry per declared output, at any module depth, and each value is the published value, the same value as Find[types.Output](c, address).Value. Use Find, FindByType or All with types.Output to work with the output entities themselves.
func (*Config) ResourceCount
deprecated
func (*Config) Validate ¶
Validate parses config from the given paths and reports whether it is valid, without executing plugins and without creating, changing or removing anything. A nil error means the configuration is valid; otherwise the returned error collects every problem found. Validates:
- HCL syntax and schema
- DAG has no cycles
- Resource dependencies are valid
func (*Config) ValidateContext ¶ added in v0.4.0
ValidateContext is Validate under the caller's context. Validate calls no provider, so ctx is observed only before the parse starts: a ctx that is already cancelled returns an error wrapping context.Canceled, or context.DeadlineExceeded when a deadline passed, and a validation that was already running finishes as it would have.
type ConfigOption ¶
ConfigOption is a functional option for configuring Config
func WithEventBufferSize ¶
func WithEventBufferSize(size int) ConfigOption
WithEventBufferSize sets the number of events that can wait to be delivered to the event handler. Once the buffer is full, emitting waits for the handler to catch up instead of dropping events, and the handler is then sent one blocked event saying how long emitting waited. A size below 1 is treated as 1. The default is DefaultEventBufferSize.
func WithEventData ¶
func WithEventData(level EventDataLevel) ConfigOption
WithEventData says what resource data lifecycle events carry.
Events carry none by default, so a resource's configuration and state do not travel through an event handler unless an application asks for them. EventDataRaw carries the resource as it was before the provider was called. EventDataProcessed carries, on a success event, the resource as xcl records it in state, which is the form EncodeSavedEntity reads.
Sensitive values in event data are masked by the event masker, see WithEventMask, and in state by the state masker, see WithStateMask. Processed event data is therefore what state holds only where both mask alike.
func WithEventHandler ¶
func WithEventHandler(handler EventHandler) ConfigOption
WithEventHandler sets the receiver for every event Validate, Apply and Destroy produce: the operation starting and finishing, each block being parsed, each provider call starting, succeeding or failing, plugin log messages, warnings and errors. The handler is called one event at a time and in the order the events were emitted, never concurrently. Emitting an event never waits for the handler, only for space in the buffer, see WithEventBufferSize, and every event of a call has been delivered before the call returns. Without a handler xcl produces no output at all.
A panic in the handler is not recovered: xcl starts no new provider call, lets the calls in progress finish and saves state, then the panic continues from the Validate, Apply or Destroy call with its original value and stack.
func WithEventMask ¶
func WithEventMask(m mask.Masker) ConfigOption
WithEventMask masks every sensitive value in the resource data events carry with m, for example mask.HashHMACSHA256, which lets a receiver correlate values without seeing them. The default is mask.Redact(), which shows each sensitive value as an envelope holding the marker:
{"xcl_masked":"redact","value":"(sensitive)"}
Only Event.Data is affected: errors and log details always show the marker. A nil masker fails NewConfig. When WithEventMask and WithNoEventMask are both given, the one given last is used.
func WithNoEventMask ¶
func WithNoEventMask() ConfigOption
WithNoEventMask turns event masking off, so the resource data events carry holds real sensitive values. Use it only when every event receiver is trusted with secrets. Errors and log details still show the marker. When WithEventMask and WithNoEventMask are both given, the one given last is used.
func WithRegistry ¶
func WithRegistry(r registry.Registry) ConfigOption
WithRegistry adds a registry the Config gets its Go types and plugins from. It may be given any number of times: registries are read, and their plugins load, in the order they were given, and within a registry its plugins load in the order they were registered. NewConfig reads every registry's types and returns an error when they clash. Nothing is loaded until the first operation that needs plugins. A nil registry is a programmer error and panics.
func WithStateMask ¶
func WithStateMask(m mask.Masker) ConfigOption
WithStateMask encrypts every sensitive value written to state with m, and opens it again when state is loaded. State then never holds a sensitive value in plain text. m is usually mask.EncryptAES256GCM, with a key kept wherever the application keeps its secrets.
m must implement mask.Reversible, since state is read back to the real value. A one-way masker, such as mask.HashHMACSHA256, mask.Omit or mask.Redact, fails NewConfig with ErrMaskNotReversible, and so does nil.
Loading state that holds a value this masker cannot open, because it was written under a different key or by a different masker, fails with ErrUnrecoverable rather than losing the value. State written in plain text still loads, and is encrypted on the next save.
func WithStatePath ¶
func WithStatePath(dir string) ConfigOption
WithStatePath persists state in a state.FileStateStore that keeps its file in the directory dir, creating the directory when it does not exist. NewConfig returns an error when the store cannot be created. When both WithStatePath and WithStateStore are given, the one given last is used. Without either, nothing is persisted; this is the supported mode for configuration-only use.
func WithStateStore ¶
func WithStateStore(ss state.StateStore) ConfigOption
WithStateStore sets the state store for persistence Uses the existing state.StateStore interface from state/state_store.go Without WithStateStore or WithStatePath nothing is persisted; this is the supported mode for configuration-only use.
func WithVariables ¶
func WithVariables(vars map[string]any) ConfigOption
WithVariables sets variables to pass to HCL parsing
type EncodeOption ¶
type EncodeOption func(*encodeOptions)
EncodeOption configures how an entity is written as configuration text. Construct one with IncludeComputed, IncludeEmpty, RevealSensitive or ShowReferences.
func IncludeComputed ¶
func IncludeComputed() EncodeOption
IncludeComputed also writes the fields a provider fills in, such as an address or an id the provider assigned.
Text written this way is for reading. xcl refuses a configuration that sets a computed field, because the provider would overwrite it, so output made with this option does not validate. Leave it off for text that has to read back.
func IncludeEmpty ¶
func IncludeEmpty() EncodeOption
IncludeEmpty also writes the attributes that hold nothing. Without it an optional attribute at its zero value is left out, and so is one that is not set, a nil pointer, slice or map, since leaving either out reads back to the same value. With it, an optional attribute is written at its zero value, and one that is not set is written as the zero value of the type it would hold: "" for a *string, [] for a slice, {} for a map. Unset blocks are still left out.
Text written this way is for reading every field. It does not read back exactly: an unset field is written the same way as one set to its zero value, so a nil *string reads back as a pointer to "", and a nil slice or map as an empty one.
func RevealSensitive ¶
func RevealSensitive() EncodeOption
RevealSensitive writes the real value of each sensitive field. Without it, each sensitive value is written as the string "(sensitive)", types.SensitiveMarker.
A value read back from the marker, such as from event data, has no real value to show, so it is written as the marker even with this option.
func ShowReferences ¶
func ShowReferences() EncodeOption
ShowReferences writes each field whose value referred to another entity as the user wrote it, such as x = resource.b.one.y or a template mixing a reference with text, instead of the value it resolved to. Only the fields the text already holds are changed, so a field that is left out stays out.
Text written this way is still for reading. A sensitive field shows its reference only when it was written as a single bare reference, such as password = variable.db_password, since an address holds no secret. Written any other way it is still shown as types.SensitiveMarker, unless RevealSensitive is also given.
The references come from the entity's own bookkeeping, so the text is the same from a live entity and from its saved data. Data saved by an earlier version of xcl holds no references and is written with resolved values.
type Event ¶
Event is one thing xcl or a plugin reports, such as a provider's Create starting or succeeding for a resource, a plugin loading, or a log message. See the events package for its fields and the names they take. An event delivered by a Config that carries resource data returns, from Entity, the entity that data holds as the Go type registered for it, with sensitive values masked.
type EventDataLevel ¶
EventDataLevel says what resource data lifecycle events carry, set with WithEventData.
type EventHandler ¶
EventHandler receives every event produced by Validate, Apply and Destroy. It is called one event at a time, in the order the events were emitted, never concurrently, and every event of a call has been delivered before the call returns.
type FunctionNameClashError ¶ added in v0.3.0
type FunctionNameClashError = xclerrors.FunctionNameClashError
FunctionNameClashError is returned when a function name is offered twice, it names both providers and their registries. NewConfig returns it for an application function named like a builtin or like another application function, and the first operation that loads plugins for a clash involving a plugin
type InvalidDecodeTargetError ¶
type InvalidDecodeTargetError = xclerrors.InvalidDecodeTargetError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type InvalidFunctionError ¶ added in v0.3.0
type InvalidFunctionError = xclerrors.InvalidFunctionError
InvalidFunctionError is returned by NewConfig for an application function whose signature cannot be called from configuration, naming the function and its registry
type InvalidSavedDataError ¶
type InvalidSavedDataError = xclerrors.InvalidSavedDataError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type InvalidThemeError ¶
type InvalidThemeError = xclerrors.InvalidThemeError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type InvalidTypeError ¶ added in v0.3.0
type InvalidTypeError = xclerrors.InvalidTypeError
InvalidTypeError is returned when a Go type has a field configuration cannot be decoded into, such as a block field that is a string: by NewConfig for a declared Go type, and when plugins load for a plugin's type. It names the type, its provider and the field, and is never a panic
type MaskNotReversibleError ¶
type MaskNotReversibleError = xclerrors.MaskNotReversibleError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type NotAnEntityError ¶
type NotAnEntityError = xclerrors.NotAnEntityError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type NotEncodableError ¶
type NotEncodableError = xclerrors.NotEncodableError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type NotFoundError ¶
type NotFoundError = xclerrors.NotFoundError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type NotRegisteredError ¶
type NotRegisteredError = xclerrors.NotRegisteredError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type NotTypeableError ¶
type NotTypeableError = xclerrors.NotTypeableError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type NotUniqueError ¶
type NotUniqueError = xclerrors.NotUniqueError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type PluginInstallError ¶ added in v0.2.0
type PluginInstallError = xclerrors.PluginInstallError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type PluginLoadError ¶
type PluginLoadError = xclerrors.PluginLoadError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type TypeFormError ¶
type TypeFormError = xclerrors.TypeFormError
TypeFormError is returned when a type uses a keyword in the other form from the one it already has: by NewConfig for a declared Go type, and when plugins load for a plugin's type
type TypeMismatchError ¶
type TypeMismatchError = xclerrors.TypeMismatchError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type TypeNameClashError ¶
type TypeNameClashError = xclerrors.TypeNameClashError
TypeNameClashError is returned when a block type is provided twice, it names both providers and their registries. NewConfig returns it for two declared Go types or a declared type with a builtin name, and the first operation that loads plugins for a clash involving a plugin
type UnknownTypeError ¶
type UnknownTypeError = xclerrors.UnknownTypeError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type UnrecoverableError ¶
type UnrecoverableError = xclerrors.UnrecoverableError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
type UnregisteredTypeError ¶
type UnregisteredTypeError = xclerrors.UnregisteredTypeError
The detail carried by each of the errors above, recovered with errors.As. These are aliases, so a caller names them here without importing a second package called errors.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
xcl-core
command
Command xcl-core is the xcl engine as a program a host in any language starts and talks to, the transport every language binding ships.
|
Command xcl-core is the xcl engine as a program a host in any language starts and talks to, the transport every language binding ships. |
|
xcl-release
command
Command xcl-release makes the decisions behind automated releases for xcl and every language binding.
|
Command xcl-release makes the decisions behind automated releases for xcl and every language binding. |
|
Package coreservice implements CoreService, the message API through which a host written in another language drives the xcl engine.
|
Package coreservice implements CoreService, the message API through which a host written in another language drives the xcl engine. |
|
Package diff holds the result of comparing an xcl configuration with the state its last apply saved: what an apply of that configuration would do, without doing any of it.
|
Package diff holds the result of comparing an xcl configuration with the state its last apply saved: what an apply of that configuration would do, without doing any of it. |
|
e2e
|
|
|
fixtures/externalplugin
command
Command externalplugin is the end-to-end suite's external plugin.
|
Command externalplugin is the end-to-end suite's external plugin. |
|
fixtures/inprocess
Package inprocess is the end-to-end suite's in-process plugin.
|
Package inprocess is the end-to-end suite's in-process plugin. |
|
fixtures/kube
Package kube holds the block types the end-to-end suite's Kubernetes-like configuration, testdata/kube, decodes into.
|
Package kube holds the block types the end-to-end suite's Kubernetes-like configuration, testdata/kube, decodes into. |
|
fixtures/recorder
Package recorder is an end-to-end fixture that records what xcl tells a provider has changed.
|
Package recorder is an end-to-end fixture that records what xcl tells a provider has changed. |
|
fixtures/services
Package services holds the block types the end-to-end suite's plugin configuration, testdata/plugin, applies.
|
Package services holds the block types the end-to-end suite's plugin configuration, testdata/plugin, applies. |
|
Package entity holds the shared vocabulary for what happens to an entity, anything an xcl configuration declares, when a new configuration is applied.
|
Package entity holds the shared vocabulary for what happens to an entity, anything an xcl configuration declares, when a new configuration is applied. |
|
Package events defines the single event shape that xcl and its plugins use to report everything they do: resource lifecycle steps, plugin discovery and loading, warnings, errors and log messages.
|
Package events defines the single event shape that xcl and its plugins use to report everything they do: resource lifecycle steps, plugin discovery and loading, warnings, errors and log messages. |
|
example
|
|
|
plugin
module
|
|
|
plugin/plugins/docker
module
|
|
|
prettylog
module
|
|
|
Package highlight turns labelled text into output, plain or coloured.
|
Package highlight turns labelled text into output, plain or coloured. |
|
internal
|
|
|
catalog
Package catalog is the private catalog of block types and the plugin loader owned by one Config.
|
Package catalog is the private catalog of block types and the plugin loader owned by one Config. |
|
cty
Package cty (pronounced see-tie) provides some infrastructure for a type system that might be useful for applications that need to represent configuration values provided by the user whose types are not known at compile time, particularly if the calling application also allows such values to be used in expressions.
|
Package cty (pronounced see-tie) provides some infrastructure for a type system that might be useful for applications that need to represent configuration values provided by the user whose types are not known at compile time, particularly if the calling application also allows such values to be used in expressions. |
|
cty/convert
Package convert contains some routines for converting between cty types.
|
Package convert contains some routines for converting between cty types. |
|
cty/ctydebug
Package ctydebug contains some utilities for cty that are aimed at debugging and test code rather than at production code.
|
Package ctydebug contains some utilities for cty that are aimed at debugging and test code rather than at production code. |
|
cty/ctystrings
Package ctystrings is a collection of string manipulation utilities which intend to help application developers implement string-manipulation functionality in a way that respects the cty model of strings, even when they are working in the realm of Go strings.
|
Package ctystrings is a collection of string manipulation utilities which intend to help application developers implement string-manipulation functionality in a way that respects the cty model of strings, even when they are working in the realm of Go strings. |
|
cty/function
Package function builds on the functionality of cty by modeling functions that operate on cty Values.
|
Package function builds on the functionality of cty by modeling functions that operate on cty Values. |
|
cty/function/stdlib
Package stdlib is a collection of cty functions that are expected to be generally useful, and are thus factored out into this shared library in the hope that cty-using applications will have consistent behavior when using these functions.
|
Package stdlib is a collection of cty functions that are expected to be generally useful, and are thus factored out into this shared library in the hope that cty-using applications will have consistent behavior when using these functions. |
|
cty/gocty
Package gocty deals with converting between cty Values and native go values.
|
Package gocty deals with converting between cty Values and native go values. |
|
cty/json
Package json provides functions for serializing cty types and values in JSON format, and for decoding them again.
|
Package json provides functions for serializing cty types and values in JSON format, and for decoding them again. |
|
declaration
Package declaration checks the shape of a plain Go type declared as a block type.
|
Package declaration checks the shape of a plain Go type declared as a block type. |
|
eventstream
Package eventstream delivers the events of one operation to the application's receiver.
|
Package eventstream delivers the events of one operation to the application's receiver. |
|
plaintype
Package plaintype lets a plain Go struct be a block type.
|
Package plaintype lets a plain Go struct be a block type. |
|
release
Package release holds the decisions behind automated releases: which release size a pull request's labels name, the next version a merge produces, and how big the step between two versions is.
|
Package release holds the decisions behind automated releases: which release size a pull request's labels name, the next version a merge produces, and how big the step between two versions is. |
|
savedentity
Package savedentity reads one saved entity record back into its typed Go value.
|
Package savedentity reads one saved entity record back into its typed Go value. |
|
test_fixtures/plain
Package plain holds block types written as plain structs, with no types.ResourceBase, for the tests of plain type support.
|
Package plain holds block types written as plain structs, with no types.ResourceBase, for the tests of plain type support. |
|
test_fixtures/plugins/functions
command
Package main is an external test plugin that offers a function to configuration.
|
Package main is an external test plugin that offers a function to configuration. |
|
test_fixtures/plugins/functions_clash
command
Package main is an external test plugin that offers the same function name as the functions fixture plugin, greet, from the provider of a different block type, salute, so a test can load both and see the clash reported.
|
Package main is an external test plugin that offers the same function name as the functions fixture plugin, greet, from the provider of a different block type, salute, so a test can load both and see the clash reported. |
|
test_fixtures/plugins/plain
command
Package main serves plainplugin as a plugin binary, so its plain types cross the plugin process boundary.
|
Package main serves plainplugin as a plugin binary, so its plain types cross the plugin process boundary. |
|
test_fixtures/plugins/plain/plainplugin
Package plainplugin is a test plugin whose types are plain structs, with no types.ResourceBase: gadget, named by its label field, hub, a singleton with neither label fields nor a Meta field, and layout, whose columns and rows hold each other.
|
Package plainplugin is a test plugin whose types are plain structs, with no types.ResourceBase: gadget, named by its label field, hub, a singleton with neither label fields nor a Meta field, and layout, whose columns and rows hold each other. |
|
test_fixtures/plugins/subtypeless
command
Package main is an external test plugin that provides one block type with no subtype, widget, written widget "<name>" {}.
|
Package main is an external test plugin that provides one block type with no subtype, widget, written widget "<name>" {}. |
|
test_fixtures/registered
Package registered holds plain Go types that tests register with PluginRegistry.RegisterType, they have no plugin and no provider.
|
Package registered holds plain Go types that tests register with PluginRegistry.RegisterType, they have no plugin and no provider. |
|
testutil
Package testutil holds the test helpers shared by more than one package, among them a fake GitHub plugin release served from a local HTTP server (NewFakeGitHubRelease) and the fixture plugin binary it packs (BuildFixturePlugin).
|
Package testutil holds the test helpers shared by more than one package, among them a fake GitHub plugin release served from a local HTTP server (NewFakeGitHubRelease) and the fixture plugin binary it packs (BuildFixturePlugin). |
|
wire
Package wire serialises values as JSON with the real value of every types.Sensitive they hold.
|
Package wire serialises values as JSON with the real value of every types.Sensitive they hold. |
|
xcl
Package hcl contains the main modelling types and general utility functions for HCL.
|
Package hcl contains the main modelling types and general utility functions for HCL. |
|
xcl/ext/customdecode
Package customdecode contains a HCL extension that allows, in certain contexts, expression evaluation to be overridden by custom static analysis.
|
Package customdecode contains a HCL extension that allows, in certain contexts, expression evaluation to be overridden by custom static analysis. |
|
xcl/gohcl
Package gohcl allows decoding HCL configurations into Go data structures.
|
Package gohcl allows decoding HCL configurations into Go data structures. |
|
xcl/hclparse
Package hclparse has the main API entry point for parsing both HCL native syntax and HCL JSON.
|
Package hclparse has the main API entry point for parsing both HCL native syntax and HCL JSON. |
|
xcl/hclsyntax
Package hclsyntax contains the parser, AST, etc for HCL's native language, as opposed to the JSON variant.
|
Package hclsyntax contains the parser, AST, etc for HCL's native language, as opposed to the JSON variant. |
|
xcl/hclwrite
Package hclwrite deals with the problem of generating HCL configuration and of making specific surgical changes to existing HCL configurations.
|
Package hclwrite deals with the problem of generating HCL configuration and of making specific surgical changes to existing HCL configurations. |
|
xcl/json
Package json is the JSON parser for HCL.
|
Package json is the JSON parser for HCL. |
|
xcl/tags
Package tags parses the `xcl` struct tags that describe how configuration maps onto Go types.
|
Package tags parses the `xcl` struct tags that describe how configuration maps onto Go types. |
|
Package mask turns sensitive values into masked data, and back again where that is possible.
|
Package mask turns sensitive values into masked data, and back again where that is possible. |
|
Package plugins provides interfaces and types for implementing HCL resource providers.
|
Package plugins provides interfaces and types for implementing HCL resource providers. |
|
example
command
|
|
|
Package registry defines where a Config gets its block types, functions and plugins from.
|
Package registry defines where a Config gets its block types, functions and plugins from. |
|
Package xclviper lets Viper read configuration written in xcl.
|
Package xclviper lets Viper read configuration written in xcl. |