Help us shape the future of Go! Take the 2026 Go Developer Survey

xcl

package module
v0.11.1 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2026 License: Apache-2.0 Imports: 38 Imported by: 2

README

XCL Configuration Language

Go Reference

XCL is a configuration language for describing things and how they relate to each other. It builds on the readability of HCL (blocks, attributes and expressions) and adds what modern configuration needs:

  • References: any value in a block can come from another block, such as a database's address or a generated password, even one that only exists once that block has been created. XCL works out the value for you.
  • Graph based processing: those references form a directed acyclic graph, so every block is processed in dependency order and a value is always set before anything reads it.
  • Plugins: block types, and the providers that create, read, update and destroy them, come from plugins run in-process or as separate programs, and installed from local paths or signed releases.

It also has variables, outputs, modules, functions and state, so a configuration can be planned, applied, changed and destroyed. Functions come built in, from the application embedding XCL, or from plugins, and are all called the same way from configuration.

XCL starts from HCL's syntax but does not aim to be compatible with Terraform configuration or other HCL dialects. Where XCL can be clearer or do more, it will diverge.

This repository is the Go implementation: you define block types as Go structs, without needing to know the HCL library underneath. Implementations for Python, JavaScript and other languages are planned.

Block types

Every block type is registered with a type and, optionally, a subtype. They become the block's labels, followed by its name, and the address other blocks use to refer to it:

database "postgres" "main" {
  location = "localhost"
  port     = 5432
  username = "admin"
  password = env("DB_PASSWORD")
}

app "web" {
  database_location = database.postgres.main.location
  connection_string = database.postgres.main.connection_string
}
  • database "postgres" "main" has the type database, the subtype postgres and the name main. Other blocks refer to it as database.postgres.main.
  • app "web" has the type app, no subtype, and the name web. Other blocks refer to it as app.web.

A subtype groups related block types under one type: database "postgres" and database "mysql" can be different Go types with different attributes, provided by different plugins.

How configuration is processed

Processing happens in two steps.

Step 1: build the graph

XCL reads every file and finds the references between blocks. app.web reads two values from database.postgres.main, so it depends on it:

app.web
└── database.postgres.main

References and depends_on together form a directed acyclic graph. A cycle is reported as an error.

Step 2: walk the graph

The graph is walked in dependency order. database.postgres.main is processed first: its provider creates the database and sets connection_string, a computed value only the provider knows. app.web is processed next, with its references filled in from the database's values. Blocks with no dependency between them are processed at the same time, and destroying runs in reverse order.

Quick start

Configuration only

An application that only reads its configuration declares each Go type, on a local registry, under the block type name it is written with, applies the configuration and reads it back. No plugin and no provider is needed. A block type is a plain struct of the application's own:

type PostgreSQL struct {
	Engine string     `xcl:"engine,label"` // the block's labels, filled by xcl:
	Name   string     `xcl:"name,label"`   // database "postgres" "main"
	Port   int        `xcl:"port,optional"`
	Meta   types.Meta // the block's id, file and line, filled by xcl
}

local := registry.NewLocal()
registry.Register[resources.Deployment](local, "deployment") // deployment "api" {}
registry.Register[resources.Service](local, "service")       // service "api" {}
registry.Register[PostgreSQL](local, "database", "postgres") // database "postgres" "main" {}

c, err := xcl.NewConfig(xcl.WithRegistry(local))
if err != nil {
	return err
}

if err := c.Apply("./config"); err != nil {
	return err
}

var cfg appConfig
err = c.Decode(&cfg)

A field tagged as a label is filled from the block's labels and can be read in expressions like an attribute (database.postgres.main.name), and a field called Meta, a types.Meta, receives the block's metadata, its disabled flag and dependencies among it (Meta.Disabled, Meta.DependsOn). Configuration sets disabled and depends_on on any block; a type declares no fields by those names. A plugin's types are written the same way. A type does not embed types.ResourceBase: xcl stores each type as one built from it that does. On Go 1.27 the declaration is also a method, local.Register[PostgreSQL]("database", "postgres"), and RegisterType(&PostgreSQL{}, ...) remains for a type only known at run time.

A plain type that cannot read a name, having neither label fields nor a Meta field, is a singleton: its block is written without labels, runner { server = "..." }, it is addressed by its type alone, as runner.server, and a second runner block in the same module is an error. A singleton takes no subtype.

To read configuration through Viper, the github.com/jumppad-labs/xcl/viper package returns a Viper that reads .xcl files into the same plain types, as keys such as database.postgres.main.port and, for a singleton, runner.server. xclviper.Read reads a file or a whole directory of them:

v := xclviper.New(
	xclviper.Type[Runner]("runner"),
	xclviper.Type[PostgreSQL]("database", "postgres"),
)
err := xclviper.Read(v, "./config")

No state. Without WithStatePath or WithStateStore nothing is persisted: the applied configuration is held in memory only. This is the supported mode for configuration-only use. Give WithStatePath a directory to keep state between runs, so a later run can plan, update and destroy what an earlier one applied.

With plugins

Plugins come from registries, the same place Go types are declared. The local registry holds plugins compiled into the program, plugin binaries named by path, and directories searched for plugin binaries. Registering only records a plugin, nothing is started until the first operation needs it:

local := registry.NewLocal()
local.RegisterPlugin(&template.TemplatePlugin{})        // an in-process plugin
local.RegisterExternalPlugin("./bin/xcl-plugin-docker") // an external plugin binary
local.RegisterPluginDirectory("~/.xcl/plugins")         // a directory to search

c, err := xcl.NewConfig(
	xcl.WithRegistry(local),
	xcl.WithStatePath("./.xcl"),
)

WithRegistry may be given more than once. Registries load in the order they were given, and the plugins of each in the order they were registered. One registry can hold Go types and plugins together. WithRegistry is the one way a Config gets anything beyond the builtins, and the registry the one place types and plugins are registered.

A plugin published as GitHub releases installs with one line from the GitHub registry, which downloads, verifies and caches the build for the current platform, see Installing plugins from GitHub:

gh := registry.NewGitHub(registry.GitHubTrustedKeys(publicKey))
gh.RegisterPlugin("jumppad-labs/xcl-plugin-docker", "v0.2.0")

Writing a plugin. Start from the plugin template, a GitHub template repository with one working entity type that runs both in-process and as a separate program, tests against strict doubles and publishes signed releases the GitHub registry installs. It follows the standard plugin layout every xcl plugin uses.

Registration problems. Registration returns no errors. Problems are reported in one of three places:

  • A mistake in a single call, wrong on every run, panics straight away naming the type: an empty name, more than one subtype or an empty subtype, a prototype that is not a pointer to a struct, a plain struct xcl cannot lay out (such as one declaring an attribute called meta, or a Meta field that is not a types.Meta), or a nil plugin or registry.
  • Declared Go types that do not fit together are an error returned by NewConfig: the same block type declared twice, in one registry or across two, or with a builtin name, is a *xcl.TypeNameClashError naming both Go types and their registries, and a type keyword used both with and without a subtype is a *xcl.TypeFormError.
  • A problem with the environment is returned by the first Validate, Apply, Destroy, Diff or Load: any missing or failing plugin, including one found in a plugin directory, as a *xcl.PluginLoadError (matching xcl.ErrPluginLoad), and a block type a plugin provides that a declared type or another plugin already provides as a *xcl.TypeNameClashError naming both providers and their registries.

Documentation

The documentation lives at xcl.dev:

Examples

Each example under example is a Go module of its own, and runs with make run:

make test-examples builds, vets and tests every example.

Other languages

The engine is available to Python as the xcl-lang package, pip install xcl-lang, imported as xcl, from jumppad-labs/xcl-python: the same engine, bundled in the wheel as the xcl-core program and run as a subprocess on every platform, Alpine included, with no shared library to load, and a synchronous and an asyncio API. Go users are unaffected: the Go library needs no cgo, and nothing in it changes for the binding.

Each language package has its own version and bundles the engine release it pins; see Releases.

Releases

Releases are automatic. Every pull request carries exactly one release label, and merging it tags and releases the next version; nobody tags by hand.

Label Use it for From v0.7.2
patch fixes, and changes that need no action from users v0.7.3
minor new features, and, before 1.0, breaking changes v0.8.0
major breaking changes after 1.0; below 1.0 it releases 1.0.0 v1.0.0
no-release CI, docs and other changes that should not ship nothing

A pull request with no release label, or with more than one, fails its release-label / release-label check and can't be merged. Labels can be changed until the moment of merging; the check re-runs on each change.

What merging does. The Tag workflow finds the merged pull request, works out the next version from its label and the latest v* tag, and pushes the tag. The tag starts Release, which builds, signs and publishes the engine archives with notes listing the merged pull requests, then tells each language binding about the new engine.

Language bindings are checked on every pull request. Every xcl pull request runs the full xcl-python test suite against the pull request's own commit, as the python / ... checks. The required bindings check passes only when they all pass, so a change that breaks a binding is found before it merges, not at release time.

When a change has to break a binding on purpose, a maintainer adds the breaks-bindings label: the binding suite is skipped and bindings passes. The binding is then fixed in its own repository, in the engine update pull request described below. Only people who can label pull requests can apply it, and removing it runs the suite again.

Languages have their own versions. Each binding repository uses the same four labels and the same automatic tagging, with its own version line. It records the engine release it bundles and tests against in xcl-ref.txt, its engine pin, so a fix in a binding releases that binding alone, against the engine it already pins.

Engine releases reach every language by themselves. Each xcl release opens a pull request in each binding that moves the pin to the new tag, labelled with the same size as the engine release (an engine patch gives a binding patch, and so on). It merges itself once the binding's checks pass, and that merge releases the binding. If the checks fail it stays open for a maintainer to fix on the same branch, and nothing is published.

For example, with xcl-python at v0.1.6 bundling engine v0.1.2:

  1. A Python-only fix merged in xcl-python with patch releases Python v0.1.7, still on engine v0.1.2. Nothing else is released.
  2. An engine fix merged in xcl with patch first passes the Python suite against its own commit. Merging it releases xcl v0.1.3, which opens "Use xcl engine v0.1.3" in xcl-python. That passes, merges itself, and releases Python v0.1.8 bundling engine v0.1.3.

Changing xcl and a binding together. To prove an engine change and the binding fix it needs work together before either merges:

  1. Open the xcl pull request, say on branch feature-x. Its bindings check is red, since it tests the binding's main.
  2. Open the binding pull request with the fix, and set its xcl-ref.txt to feature-x (or the xcl pull request's head commit). The binding's CI builds the engine from that ref, so green checks prove the pair. Don't merge it like this: a release downloads the engine from an xcl release, so on main the pin must be a released tag.
  3. Merge the xcl pull request with breaks-bindings. xcl releases, say v0.9.0, and the binding's "Use xcl engine v0.9.0" pull request opens red.
  4. Move the fix onto it. Either push the binding pull request's commits to the engine/v0.9.0 branch, keeping the pin at v0.9.0, and close the binding pull request. Or set the binding pull request's pin to v0.9.0, merge it, and close the engine update. Either way, give it the label the binding's own change needs, not just the engine's.

Every binding gets its own engine update, so bindings can be fixed and released in any order. breaks-bindings skips every binding's suite, though, so check the last red run's results for each language before adding it: one language breaking on purpose can hide another breaking by accident. Don't re-run a binding's engine bump for the same tag once someone has pushed a fix to its branch: it resets the branch from main.

Adding a language. A new binding repository provides:

  • a reusable test suite workflow, called with the binding ref and the xcl ref to test, ending in one result job; xcl's bindings.yml calls it next to the Python one;
  • three thin workflows: release-label.yml and tag.yml, which call xcl's shared release-label-check.yml and auto-tag.yml, and an engine bump workflow, which takes xcl's xcl-release dispatch;
  • an entry in the dispatch step of xcl's release.yml;
  • the release labels, the rule requiring its checks, auto-merge, and the release bot App and its secrets, as in docs/release-setup.md.

Contributing

docs/ holds notes on how xcl is built inside: the parser and entity lifecycle, state, modules and the plugin architecture.

License

Apache 2.0, see LICENSE. The HCL library forked under internal/xcl keeps its MPL-2.0 license, see NOTICE.

Documentation

Index

Constants

View Source
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
)
View Source
const DefaultEventBufferSize = 1024

DefaultEventBufferSize is the number of undelivered events a Validate, Apply or Destroy holds when WithEventBufferSize is not used

View Source
const LineEnding = "\n"

Variables

View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
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.

View Source
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

func All[T any](c *Config) ([]*T, error)

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

func As[T any](entity any) (*T, error)

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

func Decode(c *Config, target any) error

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

func Find[T any](c *Config, address string) (*T, error)

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

func FindByType[T any](c *Config, path ...string) ([]*T, error)

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

func FindOne[T any](c *Config, path ...string) (*T, error)

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

func HashString(in string) string

HashString creates an MD5 hash of the given string

func ReadFileLocation

func ReadFileLocation(filename string, startLine, startCol, endLine, endCol int) (string, error)

ReadFileLocation reads a file between the given locations

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

func (c *Config) All[T any]() ([]*T, error)

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

func (c *Config) Apply(paths ...string) error

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

func (c *Config) ApplyContext(ctx context.Context, paths ...string) error

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

func (c *Config) Decode(target any) error

Decode fills target from the entities the configuration declares. See the package level Decode for the full contract.

func (*Config) Destroy

func (c *Config) Destroy() error

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

func (c *Config) DestroyContext(ctx context.Context) error

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

func (c *Config) Diff(paths []string, options ...diff.Option) (*diff.Diff, error)

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) Entities

func (c *Config) Entities() []any

GetResources returns all resources in current state

func (*Config) EntityCount

func (c *Config) EntityCount() int

ResourceCount returns number of resources in current state

func (*Config) Find

func (c *Config) Find[T any](address string) (*T, error)

Find returns the entity declared at address, as T.

See the package level Find for the full contract.

func (*Config) FindByType

func (c *Config) FindByType[T any](path ...string) ([]*T, error)

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

func (c *Config) FindEntitiesByType(path ...string) ([]any, error)

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

func (c *Config) FindOne[T any](path ...string) (*T, error)

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

func (c *Config) FindOneEntity(path ...string) (any, error)

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

func (c *Config) FindResource(path string) (any, error)

FindResource finds a resource in current state by FQRN path

func (*Config) GetResources deprecated

func (c *Config) GetResources() []any

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

func (c *Config) Load() error

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

func (c *Config) LoadContext(ctx context.Context) error

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

func (c *Config) Outputs() map[string]any

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 (c *Config) ResourceCount() int

ResourceCount returns the number of entities the configuration declares.

Deprecated: use EntityCount. It counts every kind of declaration, not only resources. This returns exactly what EntityCount returns.

func (*Config) Validate

func (c *Config) Validate(paths ...string) error

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

func (c *Config) ValidateContext(ctx context.Context, paths ...string) error

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

type ConfigOption func(*Config) error

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

type Event = events.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

type EventDataLevel = events.DataLevel

EventDataLevel says what resource data lifecycle events carry, set with WithEventData.

type EventHandler

type EventHandler = events.Handler

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.

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
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.
dag
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.

Jump to

Keyboard shortcuts

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