open

package
v1.18.0 Latest Latest
Warning

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

Go to latest
Published: Aug 2, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package open constructs live objects from resolved configuration: an object store from a store URI and its credentials, a keychain from a set of unlock credentials, and a repository client from both.

It is the other half of pkg/config. That package answers "what did the user configure"; this one answers "connect to it". The split is what decides import cost: pkg/config depends on nothing heavier than YAML parsing, so reading and validating a profiles file is cheap, while constructing an S3 or KMS client necessarily links a cloud SDK and only a caller who does that pays for it (RFC 0022 §7).

Everything the constructors need from the outside world is passed in rather than reached for. The debug sink is a writer the caller supplies, the progress reporter is a value the caller chooses, and whether an interactive password prompt is available at all is the caller's decision — this package never inspects the process's own stdin, because a library's answer to "can I prompt?" is not the same as a terminal program's.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BackupOptions

func BackupOptions(cfg config.Backup) ([]cloudstic.BackupOption, error)

BackupOptions returns the client options describing how to record a backup, including the exclude hash derived from cfg's patterns.

Prefer Backup, which constructs the source from the same resolved patterns. This exists for a caller supplying its own source.Source implementation, which must then apply cfg.Source.Excludes itself for the hash to mean anything.

func Client

func Client(ctx context.Context, cfg config.Client, opts ...Option) (*cloudstic.Client, error)

Client opens a repository client on the store described by cfg, unlocked with the credentials cfg names.

func FromProfile

func FromProfile(ctx context.Context, path, name string, opts ...Option) (*cloudstic.Client, error)

FromProfile opens a repository client on the store that profile name selects in the profiles file at path.

An empty path means the default location — profiles.yaml inside the config directory, honouring CLOUDSTIC_CONFIG_DIR (profile.DefaultPath) — so a program reading a user's profiles finds the same file the cloudstic CLI would, rather than a second one that silently disagrees.

This is the one-call form of profile.Load → Config.StoreFor → config.MergeProfileStore → Client. Configuration of your own goes in through WithDecided, which layers it over the profile with the same precedence the cloudstic CLI applies to its flags. Drop to the explicit sequence when you need the resolved configuration itself — to display it, diff it, or decide something from it before connecting; that cannot be done afterwards, since the client this returns is already connected.

A profile that names no store is an error here, because a client needs one. Config.StoreFor reports that case as a nil store without an error, for callers that have another way to reach the repository.

func Keychain

func Keychain(ctx context.Context, cfg config.Unlock, opts ...Option) (keychain.Chain, error)

Keychain assembles the credential chain that unlocks a repository, in the order the client should try them.

The order is the contract: KMS, then a raw platform key, then a password, then a recovery mnemonic, then an interactive prompt. Each is tried against the repository's key slots and the first that opens one wins, so a caller supplying several is not ambiguous — it is a preference list.

A prompt is appended only when WithPasswordPrompt supplied one *and* the configuration allows it: either nothing else is available, or a prompt was asked for explicitly, and NoPrompt is not set. A caller that supplies no prompt gets a chain that can fail but can never block waiting for input.

func Source

func Source(ctx context.Context, cfg config.Source, opts ...Option) (source.Source, error)

Source constructs the backup source described by cfg.

The result is ready to hand to Client.Backup. Exclude patterns are applied by the source itself as it walks, so a caller building a source directly gets the same filtering a backup would — but see Backup, which additionally reads cfg.ExcludeFile and derives the snapshot's exclude hash from the same list.

Secret references in the credentials are resolved by the source when it authenticates, through the resolver WithSecretResolver names.

func Store

func Store(ctx context.Context, cfg config.Store, opts ...Option) (store.ObjectStore, error)

Store constructs the object store described by cfg.

The result is a raw backend, with no repository layers on it. Pass it to cloudstic.NewClient — or to Client below, which does that — to get compression, encryption, and packing.

Types

type BackupJob

type BackupJob struct {
	Source  source.Source
	Options []cloudstic.BackupOption
}

BackupJob is a source paired with the options that describe how to record what it yields.

The two travel together because they share one derived value: the snapshot's exclude hash must be the hash of exactly the patterns the source is filtering on. Returning them separately, or deriving the hash at a second call site, is how they come to disagree — and the engine reads a mismatch as "the exclude patterns changed", forcing a full rescan (or, worse, missing one).

func Backup

func Backup(ctx context.Context, cfg config.Backup, opts ...Option) (*BackupJob, error)

Backup constructs the source and options for one backup run.

cfg.Source.ExcludeFile is read here, once, and its patterns appended to cfg.Source.Excludes — so the source filters on the full list and the exclude hash covers the same list. That hash is what the engine compares against the previous snapshot's to decide between an incremental and a full rescan, which is why deriving it is this package's job and not a caller's.

type Option

type Option func(*options)

Option configures how a store, keychain, or client is opened.

These are behaviour knobs supplied by the caller, deliberately separate from the pkg/config value types: configuration describes a repository and can be serialized, compared, and round-tripped, while these carry writers, callbacks, and interfaces that cannot.

func WithBackendWrapper

func WithBackendWrapper(fn func(store.ObjectStore) (store.ObjectStore, error)) Option

WithBackendWrapper wraps the constructed backend before the repository layers are applied on top of it, for a caller adding its own quota, rate-limit, metrics, or fault-injection decorator.

This is the supported place to intervene in the store chain. The repository decorators themselves stay internal because their composition order is a correctness and security invariant (RFC 0022 §4a); wrapping the backend underneath them carries no such hazard.

func WithDebugWriter

func WithDebugWriter(w io.Writer) Option

WithDebugWriter logs every store operation to w.

The writer is supplied rather than created here because it is usually shared with a progress reporter, so that operation logs and progress output do not interleave.

func WithDecided

func WithDecided(cfg config.Client, decided config.FieldSet) Option

WithDecided layers configuration of the caller's own over the profile: every field named in decided is taken from cfg, and the profile supplies the rest.

This is what makes FromProfile usable by a program that has a second configuration mechanism — command-line flags, its own file, a form — rather than only by one that has nothing but the profile. Without it, such a caller had to abandon FromProfile and rebuild the four steps by hand, and the cloudstic CLI itself was the clearest example of a caller it could not serve.

Pass config.FieldsSetIn(cfg) as decided when a non-empty value is what "I decided this" means for your mechanism. Pass an explicit config.NewFieldSet when empty is itself a choice you need to keep.

Precedence is the same rule config.MergeProfileStore documents, including that a decided field's secret reference is never read — so a broken reference on a field you are replacing is not an error. That is the reason this is an option on FromProfile rather than a hook that edits the resolved configuration afterwards, which could not skip the resolution.

func WithLogger

func WithLogger(w io.Writer) Option

WithLogger sends the client's debug output — its own and that of the engine and store layers it drives — to w.

This is distinct from WithDebugWriter, which traces individual store operations. A caller that wants both passes both; they are separate because per-operation tracing is far noisier than the component diagnostics, and is often wanted on its own.

func WithPasswordPrompt

func WithPasswordPrompt(resolve, wrap func() (string, error)) Option

WithPasswordPrompt makes an interactive password prompt available as a last-resort credential, used only when the configuration leaves no other way in (or asks for a prompt explicitly) and does not forbid prompting.

resolve is called to unlock an existing repository; wrap is called to choose a password for a new key slot, and should confirm it.

Supplying these is what makes prompting possible at all. That is the caller's decision to make: this package cannot tell whether a prompt would reach a human, and guessing by inspecting os.Stdin would be wrong for every caller that is not a terminal program.

func WithReporter

func WithReporter(r cloudstic.Reporter) Option

WithReporter sets the progress reporter the client reports through. Without one the client reports nothing.

func WithSecretResolver

func WithSecretResolver(r *secretref.Resolver) Option

WithSecretResolver reads the scheme://path secret references a profile names through r, instead of through the built-in backend set.

Supply one to register a scheme the built-ins do not cover — a Vault or cloud-secret-manager backend — or, in a test, to resolve references without touching a real keychain. backends.Default returns a fresh map, so the usual shape is to add to it rather than replace it.

This affects only the profile-reading entry points. Store, Keychain and Client take configuration whose secrets are already resolved.

Jump to

Keyboard shortcuts

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