Documentation
¶
Index ¶
- func Discover(sources []string) ([]string, error)
- func Exists(k NodeKind) bool
- func FileKey(filename string) string
- func FilesMatching(files []ParsedFile, dotPath string, match func(NodeKind) bool) []string
- func IsAncestorOf(candidate, anchor ParsedFile) bool
- func IsLeaf(k NodeKind) bool
- func LeafKey(dotPath string) string
- func MapDepth(data map[string]interface{}) int
- func MarkShadowed(tree map[string]*Node)
- func Merge(files []ParsedFile, mode config.MergeMode, scopePrefix string) (map[string]*Node, error)
- func OriginalFilename(wardFile string) (string, bool)
- func ToEnvEntries(tree map[string]*Node) map[string]EnvEntry
- func ToEnvEntriesFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]EnvEntry
- func ToEnvVars(tree map[string]*Node) map[string]string
- func ToEnvVarsFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]string
- func ToFlatEnvEntries(tree map[string]*Node, preferPrefix string) (map[string]EnvEntry, error)
- func WardFilename(filename string) string
- type Conflict
- type ConflictError
- type EnvConflict
- type EnvConflictError
- type EnvEntry
- type KeyNotFoundError
- type LineMap
- type Node
- type NodeKind
- type Origin
- type ParsedFile
- func FilterByAnchor(anchor ParsedFile, all []ParsedFile) []ParsedFile
- func Load(path, vaultName, vaultRoot string, dec sops.Decryptor) (ParsedFile, error)
- func LoadAll(paths []string, vaultFor func(path string) (string, string), ...) ([]ParsedFile, error)
- func SortBySpecificity(files []ParsedFile) []ParsedFile
- func TrimToScope(ancestor ParsedFile, dirFiles []ParsedFile) ParsedFile
- type Tree
- type UnsetOutcome
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Discover ¶
Discover returns all *.ward files found recursively under each source path. Order within each source is deterministic (lexicographic).
func FileKey ¶ added in v0.1.76
FileKey converts a filename to a YAML key: "service-account.json" → "service_account_json"
func FilesMatching ¶ added in v0.1.76
func FilesMatching(files []ParsedFile, dotPath string, match func(NodeKind) bool) []string
FilesMatching returns the files whose decoded data satisfies match at dotPath. It centralises the "scan every parsed file for a dot-path" loop so callers only supply the acceptance rule as a predicate over the node kind.
func IsAncestorOf ¶
func IsAncestorOf(candidate, anchor ParsedFile) bool
isAncestorOf returns true if every map-valued key in candidate exists in anchor recursively. Leaf-valued keys in candidate are ignored — an ancestor may declare attributes that the anchor doesn't have. What matters is that the anchor covers all structural branches the candidate declares.
Example: candidate has company.sectors.one.name (leaf) → ancestor of staging.ward Example: candidate has company.production (map) → NOT ancestor of staging.ward IsAncestorOf is the exported version of isAncestorOf.
func IsLeaf ¶ added in v0.1.76
IsLeaf accepts only a scalar leaf. Used to locate where a secret is defined.
func MarkShadowed ¶
MarkShadowed walks the tree and sets Overrides=true on any leaf that would be shadowed by a deeper leaf with the same key name (same as shadow rule in ToFlatEnvEntries). This lets view display shadowed leafs in orange.
func Merge ¶
Merge merges a sequence of ParsedFiles in config order (index 0 = first vault, last = last vault). Conflict rule: if two files define the exact same leaf dot-path → conflict (in MergeModeError). If they define different dot-paths they coexist in the tree regardless of depth. When scopePrefix is non-empty, conflicts outside that dot-path prefix are silently overridden.
func OriginalFilename ¶ added in v0.1.76
OriginalFilename returns the original filename from a file-secret .ward path. Returns "", false for plain .ward files (e.g. "main.ward" has no inner extension).
func ToEnvEntries ¶
ToEnvEntries is like ToEnvVars but preserves origin information.
func ToEnvEntriesFromAnchor ¶
func ToEnvEntriesFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]EnvEntry
ToEnvEntriesFromAnchor is like ToEnvVarsFromAnchor but preserves origin information.
func ToEnvVars ¶
ToEnvVars converts all leaf nodes of a merged tree into env var pairs with full path. Example: company.sectors.one.staging.database_url → COMPANY_SECTORS_ONE_STAGING_DATABASE_URL
func ToEnvVarsFromAnchor ¶
func ToEnvVarsFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]string
ToEnvVarsFromAnchor returns env vars scoped to the anchor's container level, using relative names (stripping the common ancestor prefix). Example: anchor at company.sectors.one → NAME, STAGING_DATABASE_URL, etc.
func ToFlatEnvEntries ¶
ToFlatEnvEntries returns only the leaf values as env vars using just the leaf key name (uppercased), without any path prefix. Used by ward envs/exec without --prefixed.
Shadow rule: when two dot-paths share the same leaf key name and one is a descendant of the other (e.g. app.log_level and app.config.log_level), the deeper one wins silently — the shallower is shadowed (dropped). This is NOT a conflict.
Collision: same leaf key name at unrelated dot-paths → EnvConflictError, unless preferPrefix is set — then the entry whose dot-path is under preferPrefix wins, and all other entries for that env key are discarded. Other (non-colliding) vars from the full tree are still included.
func WardFilename ¶ added in v0.1.76
WardFilename appends .ward to the basename: "service-account.json" → "service-account.json.ward"
Types ¶
type ConflictError ¶
type ConflictError struct {
Conflicts []Conflict
}
ConflictError is returned when one or more keys are defined in multiple files at the same level.
func (*ConflictError) Error ¶
func (e *ConflictError) Error() string
type EnvConflict ¶
type EnvConflict struct {
EnvKey string
DotPaths [2]string
CaseCollision bool // true when keys are the same name but different case
}
EnvConflict holds a single env var name collision between two dot-paths.
type EnvConflictError ¶
type EnvConflictError struct {
Conflicts []EnvConflict
// Cmd is the ward command that surfaced the collision ("exec", "envs",
// "inspect"). It only shapes the resolution examples. The empty value is
// treated as "exec" so an un-stamped error still reads sensibly.
Cmd string
}
EnvConflictError is returned when flat env var names collide across different dot-paths.
func (*EnvConflictError) Error ¶
func (e *EnvConflictError) Error() string
type EnvEntry ¶
type EnvEntry struct {
Value string
Origin Origin
Overrides bool // true when this value replaced a value from an ancestor file
}
EnvEntry holds an env var's value and the origin node it came from.
type KeyNotFoundError ¶ added in v0.1.76
type KeyNotFoundError struct {
DotPath string // the full path the user asked for
AtPath string // the resolved prefix where the walk broke ("" = top level)
Available []string // keys available at that level, sorted
}
KeyNotFoundError describes a dot-path that could not be resolved in a merged tree, naming where the walk broke and which keys were available there.
func (*KeyNotFoundError) Error ¶ added in v0.1.76
func (e *KeyNotFoundError) Error() string
type Node ¶
type Node struct {
Value interface{}
Origin Origin
Overrides bool // true when this value replaced a value from a less-specific (ancestor) file
Children map[string]*Node
}
Node is either a leaf value with an origin, or a nested map.
type NodeKind ¶ added in v0.1.76
type NodeKind int
NodeKind classifies what lives at a dot-path within a decrypted YAML tree.
type ParsedFile ¶
type ParsedFile struct {
File string
Data map[string]interface{}
Lines LineMap // dot-path → line number
RawLines []string // source lines for snippet display
}
ParsedFile holds the decoded content of a .ward file before merging.
func FilterByAnchor ¶
func FilterByAnchor(anchor ParsedFile, all []ParsedFile) []ParsedFile
FilterByAnchor returns files that share at least one root key with the anchor, plus the anchor itself, ordered from least specific to most specific. A file is only included as an ancestor if it is strictly less deep than the anchor (its map-branch depth is shallower than the anchor's deepest map branch).
func Load ¶
func Load(path, vaultName, vaultRoot string, dec sops.Decryptor) (ParsedFile, error)
Load decrypts and parses a .ward file into a ParsedFile. vaultName and vaultRoot identify the vault; used to derive the key prefix for file-secrets so they merge at the correct dot-path.
func LoadAll ¶
func LoadAll(paths []string, vaultFor func(path string) (string, string), dec sops.Decryptor) ([]ParsedFile, error)
LoadAll loads all files using the given decryptor. vaultFor maps each file path to its (vaultName, vaultRoot) for file-secret prefix derivation.
func SortBySpecificity ¶
func SortBySpecificity(files []ParsedFile) []ParsedFile
SortBySpecificity sorts files from least specific to most specific. Specificity = total number of dot-paths across all keys (more = more specific).
func TrimToScope ¶
func TrimToScope(ancestor ParsedFile, dirFiles []ParsedFile) ParsedFile
TrimToScope removes from ancestor's data any map branches that do not exist in any of the dir files. This prevents sibling-sector data from leaking into an unrelated dir anchor scope. Example: company.ward has sectors.one and sectors.two — when used as ancestor of a dir anchor for sectors/two, sectors.one should be stripped.
type Tree ¶ added in v0.1.76
type Tree struct {
// contains filtered or unexported fields
}
Tree is a mutable view over a decrypted YAML document. It owns all dot-path traversal so callers never re-implement the "walk maps segment by segment" loop. The zero value is not usable; build one with NewTree.
func NewTree ¶ added in v0.1.76
NewTree wraps an existing decoded YAML map. A nil map is treated as empty.
func (*Tree) Children ¶ added in v0.1.76
Children returns the immediate child key names at dotPath, or nil if the path is absent or is a leaf.
func (*Tree) Set ¶ added in v0.1.76
Set writes value at the dot-path, creating intermediate groups as needed.
func (*Tree) Unset ¶ added in v0.1.76
func (t *Tree) Unset(dotPath string) UnsetOutcome
Unset removes the leaf at the dot-path, leaving surrounding scaffold groups in place. It never removes a whole branch: a group path yields UnsetGroup.
type UnsetOutcome ¶ added in v0.1.76
type UnsetOutcome int
UnsetOutcome is the result of removing a leaf.
const ( // UnsetAbsent means there was nothing to remove. UnsetAbsent UnsetOutcome = iota // UnsetGroup means the path is a group; nothing is removed. UnsetGroup // UnsetDone means a leaf was removed. UnsetDone )