Documentation
¶
Overview ¶
Package config holds what the CLI remembers between runs: which platform to reach, which project is current, how to print.
Credentials are not here — see internal/auth. Config files get pasted into issues and synced into dotfile repos; tokens must not.
Index ¶
Constants ¶
const ( DefaultIssuer = "https://auth.leaflow.net/realms/user" // DefaultClientID is a public client dedicated to the CLI. The console's // client is confidential and cannot be reused here; a separate one also lets // the device flow be enabled for the CLI alone. DefaultClientID = "leaflow-cli" DefaultContextName = "default" )
Variables ¶
var ( // ErrConfigNotFound is only raised when a config was named explicitly and is // missing. A missing default config is normal: a fresh install has none. ErrConfigNotFound = errors.New("config file not found") ErrNoHomeDir = errors.New("cannot locate home directory") ErrConfigUnreadable = errors.New("cannot read config") ErrConfigMalformed = errors.New("malformed config") ErrNoServiceAddress = errors.New("no address for service") )
Functions ¶
Types ¶
type Config ¶
type Config struct {
Current string `mapstructure:"current" yaml:"current"`
// CredentialStore is auto, keychain or file. Not every machine has a
// keychain, and on some the prompt it raises is itself the problem.
CredentialStore string `mapstructure:"credential_store" yaml:"credential_store,omitempty"`
Contexts map[string]*Context `mapstructure:"contexts" yaml:"contexts,omitempty"`
Output string `mapstructure:"output" yaml:"output,omitempty"`
// contains filtered or unexported fields
}
func Load ¶
Load reads the config named by path, or the default one when path is empty.
Precedence is --config > LEAFLOW_CONFIG > default location, for the same reason kubectl has --kubeconfig and KUBECONFIG: in CI the config is injected by the pipeline and cannot be required to sit under $HOME.
func (*Config) Context ¶
Context returns the effective current context: a copy with defaults and environment applied.
A copy, because defaults must not reach the file. Filling them in on read and saving afterwards would freeze today's values into every config, and changing a default later would then reach nobody who had already run the CLI once.
Failing here would break `leaflow --help` on a clean machine; the useful place to stop is the first request, where the error is "not logged in".
func (*Config) CurrentName ¶
func (*Config) EditContext ¶
EditContext returns the stored context, creating it when absent. Changes made through it are what Save writes; only what a user set explicitly ends up in the file.
type Context ¶
type Context struct {
// Domain rewrites the domain part of every address a contract declares, for
// a self-hosted deployment or a local stack: compute.leaflow.cloud becomes
// compute.leaflow.test.
//
// It is a rewrite of a stated address, not a way of deriving one. Left
// empty — which is the default — the contract is used exactly as written.
Domain string `mapstructure:"domain" yaml:"domain,omitempty"`
// Endpoints overrides Domain per service, for local stacks whose addresses
// are not derivable.
Endpoints map[string]string `mapstructure:"endpoints" yaml:"endpoints,omitempty"`
// Issuer must include the realm. The end-user portal and the operator console
// are separate realms backed by separate account stores.
Issuer string `mapstructure:"issuer" yaml:"issuer,omitempty"`
// ClientID must be a public client: this binary ships to every user's machine
// and cannot hold a secret.
ClientID string `mapstructure:"client_id" yaml:"client_id,omitempty"`
// Project is the current project. A project token already names its project,
// so no request path carries one — which makes the project a property of the
// context rather than an argument to every command.
Project string `mapstructure:"project" yaml:"project,omitempty"`
// Account is a display-only snapshot taken at login.
Account string `mapstructure:"account,omitempty" yaml:"account,omitempty"`
}
Context is one "which platform, as whom, in which project" triple, modelled on kubectl's: people work against production and a local stack at the same time, and a per-command flag is something you eventually forget to pass.
func (*Context) ServiceURL ¶
ServiceURL is where a service answers.
Resolution order: an explicit override, then the contract's own address with Domain applied if one is set, then the contract's address as written.
Nothing is derived from the service name. That convention holds for every service but one, and the exception answers 404 — which reads as "no such endpoint" rather than "right address, wrong face". A contract that states no address produces an error naming the contract, because that is where the fix belongs.