config

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 9 Imported by: 0

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

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

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

func Dir

func Dir() (string, error)

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

func Load(path string) (*Config, error)

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

func (c *Config) Context() *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 (c *Config) CurrentName() string

func (*Config) EditContext

func (c *Config) EditContext(name string) *Context

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.

func (*Config) Path

func (c *Config) Path() string

func (*Config) Save

func (c *Config) Save() error

Save writes the config back with 0600: it carries no tokens, but it does say which platform and which project you work on.

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

func (x *Context) ServiceURL(service, declared string) (string, error)

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.

Jump to

Keyboard shortcuts

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