Documentation
¶
Overview ¶
yamlkit is a package for parsing, traversing, and updating lists of configuration elements, called resources, represented as yaml doc lists.
Index ¶
- Constants
- Variables
- func AddMutations(mutations, newMutations api.ResourceMutationList) (api.ResourceMutationList, bool)
- func AnchorMutationPath(doc *gaby.YamlDoc, path api.ResolvedPath) (api.ResolvedPath, bool)
- func AnchoredPathSegment(elements []*gaby.YamlDoc, index int, withContext bool) string
- func AppendCommentLines(result []string, indent string, text string) []string
- func ApplyLinePatch(target, patch string) (string, bool)
- func ApplyScalarPatch(target, patch string) (string, bool)
- func AssociativePathSegment(mergeKeys []string, mergeKeyValues []string, index int) string
- func AttributeDetailsEqual(details1, details2 *api.AttributeDetails) bool
- func AttributeValueForPath(resourceProvider ResourceProvider, path api.ResolvedPath, ...) api.AttributeValue
- func CanonicalMutationPath(path api.ResolvedPath) api.ResolvedPath
- func CanonicalizeStoredMutationPaths(mutations api.ResourceMutationList, parsedData gaby.Container, ...) (api.ResourceMutationList, bool)
- func CommentKey(ct CommentType, targetKey string) string
- func CommentKeysForDataKey(targetKey string) []string
- func ComputeLinePatch(previous, modified string) string
- func ComputeMutations(previousParsedData, modifiedParsedData gaby.Container, functionIndex int64, ...) (api.ResourceMutationList, error)
- func ComputeMutationsForDocs(rootPath string, previousDoc *gaby.YamlDoc, modifiedDoc *gaby.YamlDoc, ...)
- func ComputeScalarPatch(previous, modified string) string
- func DeletePaths(parsedData gaby.Container, ...) error
- func DiffPatch(original, modified, targetData []byte, resourceProvider ResourceProvider) ([]byte, bool, error)
- func DiffPatchWithOptions(original, modified, targetData []byte, resourceProvider ResourceProvider, ...) ([]byte, bool, error)
- func ElementDigest(element *gaby.YamlDoc) string
- func ElementIdentity(element *gaby.YamlDoc) string
- func EnrichMergeKeysFromDoc(doc *gaby.YamlDoc, resourceProvider ResourceProvider, attr *api.AttributeValue)
- func EscapeDotsInPathSegment(segment string) string
- func ExtractCommentKeys(data map[string]any) map[string]string
- func ExtractCommentsFromData(data any) (any, map[string]string)
- func FindMutationIndex(parsedData gaby.Container, mutationSources api.ResourceMutationList, ...) (int64, bool)
- func FindResourceDoc(parsedData gaby.Container, resourceProvider ResourceProvider, ...) (*gaby.YamlDoc, *api.ResourceInfo)
- func FindYAMLPathsByValue(parsedData gaby.Container, resourceProvider ResourceProvider, ...) api.AttributeValueList
- func FunctionInvocationsEqual(fi1, fi2 *api.FunctionInvocation) bool
- func GetMutationOptions(doc *gaby.YamlDoc, resourceProvider ResourceProvider) []string
- func GetNeededPaths[T api.Scalar](parsedData gaby.Container, ...) (api.AttributeValueList, error)
- func GetNeededStringPaths(parsedData gaby.Container, ...) (api.AttributeValueList, error)
- func GetPathRegistryForAttributeName(resourceProvider ResourceProvider, attributeName api.AttributeName) api.ResourceTypeToPathToVisitorInfoType
- func GetPathRegistryForAttributeNameByProperty(resourceProvider ResourceProvider, attributeName api.AttributeName, ...) api.ResourceTypeToPathToVisitorInfoType
- func GetPathVisitorInfo(resourceProvider ResourceProvider, resourceType api.ResourceType, ...) *api.PathVisitorInfo
- func GetPaths[T api.Scalar](parsedData gaby.Container, ...) (api.AttributeValueList, error)
- func GetPathsAnyType(parsedData gaby.Container, ...) (api.AttributeValueList, error)
- func GetRegisteredNeededPaths(resourceProvider ResourceProvider) api.ResourceTypeToPathToVisitorInfoType
- func GetRegisteredNeededPathsByProperty(resourceProvider ResourceProvider, neededRequired []string) api.ResourceTypeToPathToVisitorInfoType
- func GetRegisteredNeededStringPaths(parsedData gaby.Container, resourceProvider ResourceProvider, ...) (api.AttributeValueList, error)
- func GetRegisteredProvidedPaths(resourceProvider ResourceProvider) api.ResourceTypeToPathToVisitorInfoType
- func GetRegisteredProvidedStringPaths(parsedData gaby.Container, resourceProvider ResourceProvider, ...) (api.AttributeValueList, error)
- func GetResourceCategoryTypeName(doc *gaby.YamlDoc, resourceProvider ResourceProvider) (api.ResourceCategory, api.ResourceType, api.ResourceName, error)
- func GetResourceInfo(doc *gaby.YamlDoc, resourceProvider ResourceProvider) (*api.ResourceInfo, error)
- func GetStringPaths(parsedData gaby.Container, ...) (api.AttributeValueList, error)
- func GetToolchainPath(rp ResourceProvider) string
- func GetVisitorMapForPath(resourceProvider ResourceProvider, rt api.ResourceType, ...) api.ResourceTypeToPathToVisitorInfoType
- func GetVisitorOptions(doc *gaby.YamlDoc, resourceProvider ResourceProvider) []string
- func InjectCommentKeys(data map[string]any, comments map[string]string)
- func IsCommentKey(key string) bool
- func IsEmptyOrPlaceHolder(s string) bool
- func IsIntPlaceHolderValue(v int) bool
- func IsMultiLineString(s string) bool
- func IsNumber(s string) bool
- func IsNumeric(c rune) bool
- func IsPatchableString(s string) bool
- func IsPlaceholderValue(value any) bool
- func IsStringPlaceHolderValue(v string) bool
- func JoinPathSegments(segments []string) string
- func JoinRelativePath(prefix, relative string) string
- func LeadingWhitespace(line string) string
- func LowerFirst(s string) string
- func MarshalSpecSet(set SpecSet) ([]byte, error)
- func MatchesWhereResourceExpressions(doc *gaby.YamlDoc, resourceInfo *api.ResourceInfo, ...) (bool, error)
- func MergeCommentsIntoData(data any, comments map[string]string) any
- func MergeKeyIdentity(values []string) string
- func MergeKeyValues(element *gaby.YamlDoc, mergeKeys []string) ([]string, bool)
- func NameArrayElementsByMergeKey(doc *gaby.YamlDoc, path api.ResolvedPath, mergeKeyLookup MergeKeyLookup) (api.ResolvedPath, bool)
- func NormalizeStructurePath(path string) string
- func PatchMutations(parsedData gaby.Container, ...) (gaby.Container, api.MutationConflictList, error)
- func PatchMutationsGuarded(parsedData gaby.Container, ...) (gaby.Container, api.MutationConflictList, error)
- func PathIsResolved(path string, includeAt bool) bool
- func RegisterAttributeGroup(resourceProvider ResourceProvider, groupName api.AttributeName, ...)
- func RegisterDeclaredAttributePaths(resourceProvider ResourceProvider, compiled *CompiledSpecs, ...) error
- func RegisterPathsByAttributeName(resourceProvider ResourceProvider, attributeName api.AttributeName, ...)
- func ReplaceStringPlaceholder(s, replacement string) string
- func Reset(parsedData gaby.Container, mutationsProtection api.ResourceMutationList, ...) error
- func ResolveAssociativeSegments(doc *gaby.YamlDoc, path string) (string, bool)
- func ResolveAssociativeSegmentsForInsertion(doc *gaby.YamlDoc, path string) (string, bool)
- func ResolveConfigHubPath(path string, resourceInfo *api.ResourceInfo) (any, error)
- func ResourceAndCategoryTypeMaps(parsedData gaby.Container, resourceProvider ResourceProvider) (resourceMap ResourceNameToCategoryTypesMap, ...)
- func ResourceTypesForAttribute(attributeName api.AttributeName, resourceProvider ResourceProvider) []api.ResourceType
- func ResourceTypesForPathMap(pathMap map[api.ResourceType][]string) []api.ResourceType
- func SetProtection(parsedData gaby.Container, mutations api.ResourceMutationList, ...) (api.ResourceMutationList, []api.ResolvedPath)
- func SplitInlineComment(value string) (string, string)
- func StoredMutationPathsNeedRewriting(mutations api.ResourceMutationList, resourceProvider ResourceProvider) bool
- func StripAssociativeSegments(path string) string
- func StripCommentKeys(data any) any
- func StripComments(yamlData []byte) ([]byte, error)
- func SubtractMutations(mutations, subtractMutations api.ResourceMutationList) (api.ResourceMutationList, api.MutationConflictList)
- func TransformConfig(originalData []byte, resourceProvider ResourceProvider, ...) ([]byte, bool, error)
- func UpdatePathsFunction[T api.Scalar](parsedData gaby.Container, ...) error
- func UpdatePathsFunctionDoc(parsedData gaby.Container, ...) error
- func UpdatePathsSetterArgument(parsedData gaby.Container, ...) error
- func UpdatePathsValue[T api.Scalar](parsedData gaby.Container, ...) error
- func UpdateStringPaths(parsedData gaby.Container, ...) error
- func UpdateStringPathsFunction(parsedData gaby.Container, ...) error
- func VetPathsSetterArgument(parsedData gaby.Container, ...) (api.ValidationResult, error)
- func VisitPaths[T api.Scalar](parsedData gaby.Container, ...) (any, error)
- func VisitPathsAnyType(parsedData gaby.Container, ...) (any, error)
- func VisitPathsDoc(parsedData gaby.Container, ...) (any, error)
- func VisitResources(parsedData gaby.Container, output any, resourceProvider ResourceProvider, ...) (any, error)
- func VisitResourcesFiltered(parsedData gaby.Container, output any, resourceProvider ResourceProvider, ...) (any, error)
- func VisitorInfoEqual(pathVisitorInfo1, pathVisitorInfo2 *api.PathVisitorInfo) bool
- func YamlSafePathGetDoc(doc *gaby.YamlDoc, resolvedPath api.ResolvedPath, notFoundOk bool) (*gaby.YamlDoc, bool, error)
- func YamlSafePathGetValue[T api.Scalar](doc *gaby.YamlDoc, resolvedPath api.ResolvedPath, notFoundOk bool) (T, bool, error)
- func YamlSafePathGetValueAnyType(doc *gaby.YamlDoc, resolvedPath api.ResolvedPath, notFoundOk bool) (any, bool, error)
- type AttributeDescriptor
- type AttributeEnricher
- type AttributePath
- type AttributeRegistrationDetails
- type CommentType
- type CompiledSpecs
- func (c *CompiledSpecs) ApplyPriorityOf(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) (int, bool)
- func (c *CompiledSpecs) DeclaredAttributes(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) map[api.AttributeName][]AttributePath
- func (c *CompiledSpecs) ExclusiveFieldsForPath(toolchainType workerapi.ToolchainType, resourceType api.ResourceType, ...) (ExclusiveFields, bool)
- func (c *CompiledSpecs) IsMapKeyPath(toolchainType workerapi.ToolchainType, resourceType api.ResourceType, ...) bool
- func (c *CompiledSpecs) MergeKeysForPath(toolchainType workerapi.ToolchainType, resourceType api.ResourceType, ...) ([]string, bool)
- func (c *CompiledSpecs) ReferencePaths(toolchainType workerapi.ToolchainType) []DeclaredReference
- func (c *CompiledSpecs) RenderAttributes(toolchainType workerapi.ToolchainType) string
- func (c *CompiledSpecs) RenderStructure(toolchainType workerapi.ToolchainType) string
- func (c *CompiledSpecs) ResourceTypesEmbeddingShape(toolchainType workerapi.ToolchainType, shapeName string) []api.ResourceType
- func (c *CompiledSpecs) ResourceTypesWithAttributes(toolchainType workerapi.ToolchainType) []api.ResourceType
- func (c *CompiledSpecs) ResourceTypesWithScope(toolchainType workerapi.ToolchainType, scope Scope) []api.ResourceType
- func (c *CompiledSpecs) SchemaFor(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) string
- func (c *CompiledSpecs) SchemaLocationsFor(toolchainType workerapi.ToolchainType) []string
- func (c *CompiledSpecs) ScopeOf(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) Scope
- func (c *CompiledSpecs) ShapePaths(toolchainType workerapi.ToolchainType, resourceType api.ResourceType, ...) []string
- func (c *CompiledSpecs) SimilarityClassOf(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) string
- type Declaration
- type DeclaredReference
- type DerivedAttribute
- type EmbeddedAccessor
- type ExactValueMatcher
- type ExclusiveFieldGroup
- type ExclusiveFields
- type ExclusiveFieldsLookup
- type GuardFilter
- type JSONAccessor
- func (ja *JSONAccessor) Data(scalarYamlDoc *gaby.YamlDoc, path string) (any, error)
- func (ja *JSONAccessor) ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
- func (ja *JSONAccessor) Extract(currentFieldValue, path string) (any, error)
- func (ja *JSONAccessor) Replace(currentFieldValue string, value any, path string) (string, error)
- func (ja *JSONAccessor) SetP(scalarYamlDoc *gaby.YamlDoc, value any, path string) error
- type LineAccessor
- func (la *LineAccessor) Data(scalarYamlDoc *gaby.YamlDoc, path string) (any, error)
- func (la *LineAccessor) ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
- func (la *LineAccessor) Extract(currentFieldValue, path string) (any, error)
- func (la *LineAccessor) Replace(currentFieldValue string, value any, path string) (string, error)
- func (la *LineAccessor) SetP(scalarYamlDoc *gaby.YamlDoc, value any, path string) error
- type LintConfig
- type LintFinding
- type MergeKeyEntry
- type MergeKeyField
- type MergeKeyLookup
- type PathEnricher
- type RegexpAccessor
- func (ra *RegexpAccessor) Data(scalarYamlDoc *gaby.YamlDoc, path string) (any, error)
- func (ra *RegexpAccessor) ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
- func (ra *RegexpAccessor) Extract(currentFieldValue, path string) (any, error)
- func (ra *RegexpAccessor) Replace(currentFieldValue string, value any, path string) (string, error)
- func (ra *RegexpAccessor) SetP(scalarYamlDoc *gaby.YamlDoc, value any, path string) error
- type RegexpMatcher
- type ResolvedPathInfo
- type ResourceCategoryTypeToNamesMap
- type ResourceInfoToDocMap
- type ResourceNameToCategoryTypesMap
- type ResourceProvider
- type ResourceProviderRegistry
- func (r *ResourceProviderRegistry) ExclusiveFieldsForPath(resourceType api.ResourceType, path string) (ExclusiveFields, bool)
- func (r *ResourceProviderRegistry) GetAttributeRegistry() api.AttributeNameToAttributeDescriptor
- func (r *ResourceProviderRegistry) GetPathRegistry() api.AttributeNameToResourceTypeToPathToVisitorInfoType
- func (r *ResourceProviderRegistry) GetRegistry() *ResourceProviderRegistry
- func (r *ResourceProviderRegistry) IsMapKeyPath(resourceType api.ResourceType, path string) bool
- func (r *ResourceProviderRegistry) MergeKeysForPath(resourceType api.ResourceType, path string) ([]string, bool)
- type ResourceTypeSpec
- type ResourceTypeToPathPrefixSetType
- type ResourceVisitorFunc
- type Scope
- type ShapeEmbed
- type SpecSet
- type StringContainsMatcher
- type ValueMatcher
- type VisitorContext
- type VisitorFunc
- type VisitorFuncAnyType
- type VisitorFuncDoc
- type YAMLAccessor
- func (ya *YAMLAccessor) Data(scalarYamlDoc *gaby.YamlDoc, path string) (any, error)
- func (ya *YAMLAccessor) ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
- func (ya *YAMLAccessor) Extract(currentFieldValue, path string) (any, error)
- func (ya *YAMLAccessor) Replace(currentFieldValue string, value any, path string) (string, error)
- func (ya *YAMLAccessor) SetP(scalarYamlDoc *gaby.YamlDoc, value any, path string) error
Constants ¶
const ( PatchFormatJSON = "json" PatchFormatYAML = "yaml" )
Patch format constants used as the "format" field in structural patches.
const ( PlaceHolderBlockApplyString = "confighubplaceholder" PlaceHolderBlockApplyInt = 999999999 )
PlaceHolderBlockApply We will need placeholders for different data types and that fit with different validation rules The string value is all lowercase to comply with DNS label requirements.
const CommentKeyPrefix = "$comment$"
CommentKeyPrefix is the prefix for all comment keys in the data structure. Comment keys encode comments from native config formats (TOML, INI, HCL, etc.) as map entries so they survive conversion through formats like JSON that don't support comments natively.
const EmbeddedAccessorSeparator = "#"
const SchemaNone = "none"
SchemaNone is ResourceTypeSpec.Schema for a type known to have no schema anywhere. Stating it stops a validator reporting the type as validated when it was skipped, and stops a fetch that can only ever fail.
Variables ¶
var EmbeddedPathNotFound = errors.New("embedded path not found")
var NoSubexpressions = errors.New("no capturing subexpressions")
var UnsupportedAccessorType = errors.New("accessor type not supported")
var UnsupportedValueType = errors.New("only string values supported currently")
Functions ¶
func AddMutations ¶
func AddMutations(mutations, newMutations api.ResourceMutationList) (api.ResourceMutationList, bool)
AddMutations merges newMutations into mutations and returns the result, accumulating changes over sequential edits to produce a compiled history of all modifications. The accumulated form is what's stored as a Unit's MutationSources and what feeds the protection map passed into PatchMutations.
Algorithm:
Resource matching: by current ResourceTypeAndName, then by AliasesWithoutScopes (handling renames). Unmatched new mutations are appended as new resource entries.
Resource-level merge:
| Existing Type | New Type | Result | |------------------|-----------------------|---------------------| | Any | None | Keep existing | | Any | Delete or Replace | Replace with new | | None | Any (non-None) | Replace with new | | Delete | Any (non-Delete) | Change to Replace | | Add/Update | Add/Update | Merge path mutations|
Path-level merge: process newMutations' paths sorted least-specific to most-specific so parent paths land before children. Paths are keyed canonically -- see canonicalPathKeys. For each new path:
- Exact match in existing: replace the existing entry, taking the new MutationType (so a later edit's intent — e.g., an Update on a previously-Added field — is reflected). Exception: Delete → non-Delete becomes Replace, since the field was previously erased and is now being re-set. - Existing path is a child of the new path AND new path is Delete or Replace: drop the now-superseded child paths. - Otherwise: insert the new path verbatim, dropping any existing children it supersedes.
Because the new MutationType replaces the existing one on exact match, when this accumulated record is later used as a patch, PatchMutations sees the latest intent (e.g., Update to merge with the target's value rather than wholesale Replace). Both branches take the whole incoming MutationInfo, Patch included: an accumulated entry should describe the change the same way whether or not the path had been written before, and a line-level patch that survives on a fresh path and is dropped on a repeated one is a difference nothing means.
Alias tracking: union of both sides' Aliases / AliasesWithoutScopes so a resource can still be matched after another rename.
Key behaviors:
- Accumulative: designed to be called repeatedly as changes occur.
- Last-write-wins for values and types on exact-path matches.
- Alias awareness: handles resources renamed between mutation sets.
func AnchorMutationPath ¶ added in v0.2.22
func AnchorMutationPath(doc *gaby.YamlDoc, path api.ResolvedPath) (api.ResolvedPath, bool)
AnchorMutationPath re-attaches the positional fallback to every associative segment of a path, resolved against doc, and reports whether anything changed. It is CanonicalMutationPath undone against a particular document, for the one caller that needs the stored form back: a migration rolling the canonical keying of MutationSources backwards.
The index it writes is where the element sits in doc, which is what a diff computed against doc would have recorded, not necessarily what the path carried before it was canonicalized. Nothing is written when the path does not fully resolve, since a fallback pointing at the wrong element is worse than none.
func AnchoredPathSegment ¶ added in v0.2.12
AnchoredPathSegment builds the path segment naming an element of an array that has no declared merge key: the positional index, as before, plus a digest of the element's content.
The index alone says where the element sat in the configuration the patch was computed against, which is only where it sits in the target if the target has not drifted. The digest says which element it was, so a target that inserted, removed, or reordered elements around it can still be patched in the right place. Where the target has edited the element itself the digest no longer matches and resolution falls back to the index, which is where it was before anchors — the anchor can only improve the outcome.
The digest is taken from the element as it stood on the side the path names it from: the previous revision for a matched pair or a removal, the new content for an insertion. Both sides of a three-way merge diff against the same base, so their anchors for the same element agree and subtraction still recognizes them as the same path.
withContext adds the shape of the array around the element: digests of the elements on either side and the array's length. All of it describes the array the patch was computed against, so it is recorded for a path that names an element of that array — a matched element or a removal — and not for an insertion, whose index names a position in the array that only exists once the patch has been applied.
func AppendCommentLines ¶ added in v0.1.25
AppendCommentLines appends comment text as #-prefixed lines to the result slice, using the given indentation prefix to match surrounding lines.
func ApplyLinePatch ¶ added in v0.1.14
ApplyLinePatch applies a line-level patch (produced by ComputeLinePatch) to a target string. Returns the patched string and true if all hunks applied cleanly. If any hunk fails to apply, returns the partially patched string and false.
func ApplyScalarPatch ¶ added in v0.1.14
ApplyScalarPatch applies a patch (produced by ComputeScalarPatch) to a target string. It auto-detects the patch format: structural patches (JSON-encoded, start with '{') are applied structurally; line-level text patches (unified diff) are applied with fuzzy context matching.
Returns the patched string and true if the patch applied cleanly. On failure, returns the original target string and false.
func AssociativePathSegment ¶
AssociativePathSegment builds a path segment encoding the merge key values and the positional index, using the syntax ?key=value;@index — or, for an array whose elements are identified by more than one field, ?key1=value1,key2=value2;@index. Keys and values are escaped to handle dots.
func AttributeDetailsEqual ¶
func AttributeDetailsEqual(details1, details2 *api.AttributeDetails) bool
AttributeDetailsEqual reports whether two sets of attribute details, optionally including getter and setter invocations, match.
Needs/provides properties are compared for compatibility rather than equality: a path registered twice with different required values accepts either, and registerPaths unions them. A reference field naming any workload controller is registered once per controller, and those registrations agreeing about everything except which type they name is the normal case, not a mismatch to report.
func AttributeValueForPath ¶
func AttributeValueForPath(resourceProvider ResourceProvider, path api.ResolvedPath, resourceInfo *api.ResourceInfo, value any) api.AttributeValue
func CanonicalMutationPath ¶ added in v0.2.12
func CanonicalMutationPath(path api.ResolvedPath) api.ResolvedPath
CanonicalMutationPath drops the positional fallback from every associative segment of a path, turning ?key=value;@index into ?key=value.
The index in an associative segment is a fallback for resolution, not part of the element's identity: it records where the element sat in the configuration the path was computed against. Two paths that name the same element by merge key are the same path even when the element sits at different positions on either side — which it will whenever one side has added or removed an earlier element. Comparing paths between two independently computed diffs has to be done on this form; applying a path does not, since the fallback is useful there.
Splitting on "." is safe: dots within a segment are escaped as ~1.
func CanonicalizeStoredMutationPaths ¶ added in v0.4.10
func CanonicalizeStoredMutationPaths(mutations api.ResourceMutationList, parsedData gaby.Container, resourceProvider ResourceProvider) (api.ResourceMutationList, bool)
CanonicalizeStoredMutationPaths rewrites the path keys of a stored mutation record into the form today's merge keys produce, resolving positional segments against parsedData. It returns the record unchanged, and false, when there is nothing to rewrite.
Two entries that rewrite to one key are folded: they are the same element recorded at two positions, and the later one by MutationNum wins except that Protected survives from either, since a lost Protected silently reopens a path its owner had closed.
func CommentKey ¶ added in v0.1.25
func CommentKey(ct CommentType, targetKey string) string
CommentKey builds a comment map key from a comment type and target key name. For example, CommentKey(CommentHead, "server") returns "$comment$head$server". An empty targetKey refers to the containing object/document itself.
func CommentKeysForDataKey ¶ added in v0.1.25
CommentKeysForDataKey returns the $comment$ keys that could be associated with a given data key (head, line, and foot).
func ComputeLinePatch ¶ added in v0.1.14
ComputeLinePatch computes a line-level diff between two multi-line strings and returns a patch in unified diff text format. The patch can be serialized as a string in MutationInfo.Patch and later applied with ApplyLinePatch.
This uses the Myers diff algorithm via go-diff's DiffLinesToChars to tokenize at line boundaries, producing a minimal edit script that correctly identifies inserted, deleted, and unchanged lines.
func ComputeMutations ¶
func ComputeMutations(previousParsedData, modifiedParsedData gaby.Container, functionIndex int64, resourceProvider ResourceProvider) (api.ResourceMutationList, error)
ComputeMutations performs a kind of diff between two configuration Units where it determines what modifications were made at the resource/element level and at the path level. They are recorded in a way that can be accumulated and updated over subsequent edits and transformations.
func ComputeMutationsForDocs ¶
func ComputeMutationsForDocs(rootPath string, previousDoc *gaby.YamlDoc, modifiedDoc *gaby.YamlDoc, functionIndex int64, pathMutationMap api.MutationMap, mergeKeyLookup MergeKeyLookup, arrayOrders api.ArrayOrderMap, arrayElementAliases api.ArrayElementAliasMap)
arrayElementAliases, if non-nil, is populated with element-level renames detected inside merge-keyed arrays. When an unmatched modified element and an unmatched previous element are similar enough, the pair is treated as a rename: child paths are emitted under the previous merge-key value (so they align with target-side paths in SubtractMutations) and the alias is recorded so PatchMutations rewrites the merge-key field at apply time.
func ComputeScalarPatch ¶ added in v0.1.14
ComputeScalarPatch computes a patch for a changed multi-line scalar string value. It tries to parse both values as JSON, then YAML, and computes a structural patch (sub-path mutations) for those formats. Falls back to a line-level text diff.
Structural patches give true three-way merge for embedded JSON/YAML: individual field changes are tracked by path, so independent changes to different fields merge correctly. Line-level patches handle unstructured text (markdown, config files, etc.) with context-based fuzzy matching.
func DeletePaths ¶
func DeletePaths( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, options *api.FunctionOptions, ) error
func DiffPatch ¶
func DiffPatch(original, modified, targetData []byte, resourceProvider ResourceProvider) ([]byte, bool, error)
DiffPatch compares original and modified YAML content, generates a patch, and applies it to target data
func DiffPatchWithOptions ¶
func DiffPatchWithOptions(original, modified, targetData []byte, resourceProvider ResourceProvider, omitAdditions bool, options *api.FunctionOptions) ([]byte, bool, error)
DiffPatchWithOptions compares original and modified YAML content, generates a patch, and applies it to target data If omitAdditions is true, mutations of type MutationTypeAdd are filtered out before applying the patch
func ElementDigest ¶ added in v0.2.12
ElementDigest returns a short digest of an array element's content, over the parsed subtree in canonical form rather than its text: comments, key order, indentation, and quoting style do not change it, so an element that was only reformatted still matches.
func ElementIdentity ¶ added in v0.2.12
ElementIdentity returns a projection of an array element that identifies it independently of its current value, or "" when the element offers none.
Two sources, the person's first:
- A structured comment, which is the only mechanism here that lets someone *correct* the engine rather than work around it. Where a person has said which element this is, that is what it is. See identityDirective.
- A scalar holding a command-line flag with an inline value, whose identity is the flag name. An args list is the most common unkeyed array in a Kubernetes workload, and `--log.level=INFO` and `--log.level=DEBUG` are the same flag.
Either way the point is the same: an element the target has *edited* can still be found, which no digest can do, however either side has since reordered the list.
Both sides of a merge have to carry the markup for it to do anything — the source records it in the path, and the target is matched against it — so it belongs upstream, where a clone inherits it, rather than only on the variant that needed it.
func EnrichMergeKeysFromDoc ¶ added in v0.1.15
func EnrichMergeKeysFromDoc(doc *gaby.YamlDoc, resourceProvider ResourceProvider, attr *api.AttributeValue)
EnrichMergeKeysFromDoc extracts merge keys from the resolved path of an AttributeValue and adds them as NeededPreferred properties. For each numeric array index in the path, it looks up the merge key via MergeKeyForPath and reads the value from the document. For example, path "spec.template.spec.volumes.1.configMap.name" with merge key "name"="config" at volumes[1] yields NeededPreferred["Name"] = "config".
func EscapeDotsInPathSegment ¶
EscapeDotsInPathSegment escapes any dots in a path segment for use in whole-path searches because path segments are separated by dots. TODO: Escape more special characters?
func ExtractCommentKeys ¶ added in v0.1.25
ExtractCommentKeys removes comment keys from the top level of a map, returning them as a separate map from comment key to comment text. The input map is modified in place.
func ExtractCommentsFromData ¶ added in v0.1.25
ExtractCommentsFromData recursively extracts all comment keys from a data tree, returning the cleaned data and a flat map of dot-path to comment text.
func FindMutationIndex ¶
func FindMutationIndex(parsedData gaby.Container, mutationSources api.ResourceMutationList, resource api.ResourceInfo, path api.ResolvedPath, resourceProvider ResourceProvider) (int64, bool)
FindMutationIndex looks up the mutation index for a specific resource and path in a ResourceMutationList. It matches the resource by ResourceTypeAndName, handling aliases and scope changes (same pattern as AddMutations). For the path, it walks up parent paths to find the most specific mutation index, falling back to the resource-level index if no path-level match is found. Returns the mutation index and true if found.
parsedData and resourceProvider locate the resource's document, which is what turns a stored path into the positional form callers look up by -- NeededPaths addresses array elements by index. Both may be nil; the lookup then covers only the paths that match textually.
func FindResourceDoc ¶ added in v0.1.15
func FindResourceDoc( parsedData gaby.Container, resourceProvider ResourceProvider, target *api.ResourceInfo, ) (*gaby.YamlDoc, *api.ResourceInfo)
FindResourceDoc finds the document in parsedData that best matches the given target ResourceInfo. It uses the same matching hierarchy as ComputeMutations:
- Exact ResourceName or ResourceNameWithoutScope match
- ResourceTypesAreSimilar as a prerequisite for any match
Returns the matching doc and its ResourceInfo, or (nil, nil) if no match is found.
func FindYAMLPathsByValue ¶
func FindYAMLPathsByValue(parsedData gaby.Container, resourceProvider ResourceProvider, matcher ValueMatcher, options *api.FunctionOptions) api.AttributeValueList
FindYAMLPathsByValue searches for all paths whose scalar value is matched by matcher in a YAML structure and returns an api.AttributeValueList. The matched value stored in each AttributeValue is the actual value found at the path, so callers (e.g. search-replace) can transform it.
func FunctionInvocationsEqual ¶
func FunctionInvocationsEqual(fi1, fi2 *api.FunctionInvocation) bool
FunctionInvocationsEqual reports whether two function invocations match.
func GetMutationOptions ¶
func GetMutationOptions(doc *gaby.YamlDoc, resourceProvider ResourceProvider) []string
GetMutationOptions reads the MutationOptions value from a YAML document using the resource provider's context path.
func GetNeededPaths ¶
func GetNeededPaths[T api.Scalar]( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, options *api.FunctionOptions, ) (api.AttributeValueList, error)
GetNeededPaths traverses the specified path patterns of the specified resource types and returns an api.AttributeValueList containing the values and registered information about all of the found attributes matching the path patterns that Need values. Currently "Need" is determined using placeholder values, 999999999 (9 9s) for integers. Use only for ints. Bools have no placeholder value. Use GetNeededStringPaths for strings.
func GetNeededStringPaths ¶
func GetNeededStringPaths( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, options *api.FunctionOptions, ) (api.AttributeValueList, error)
GetNeededStringPaths traverses the specified path patterns of the specified resource types and returns an api.AttributeValueList containing the values and registered information about all of the found string attributes matching the path patterns that Need values. Currently "Need" is determined using placeholder values, "confighubplaceholder" for strings. It can also extract fields embedded in strings using registered embedded accessors.
func GetPathRegistryForAttributeName ¶
func GetPathRegistryForAttributeName( resourceProvider ResourceProvider, attributeName api.AttributeName, ) api.ResourceTypeToPathToVisitorInfoType
GetPathRegistryForAttributeName returns the registry for the specified attribute to pass to a visitor function. If the attribute has a non-empty AttributeGroup, the registries for all attributes in the group are combined and returned.
func GetPathRegistryForAttributeNameByProperty ¶ added in v0.4.8
func GetPathRegistryForAttributeNameByProperty( resourceProvider ResourceProvider, attributeName api.AttributeName, propertyKey string, propertyValue string, ) api.ResourceTypeToPathToVisitorInfoType
GetPathRegistryForAttributeNameByProperty returns the paths registered under an attribute whose needs/provides properties carry propertyKey with propertyValue, on either side: a provided path offering it, or a needed path requiring it.
This is how a reference selects the paths that point at one resource type. Splitting the attribute into a name per target would answer the same question by string convention, which is a second encoding of what the properties already say -- and a convention spelled differently in two places matches nothing, silently.
func GetPathVisitorInfo ¶
func GetPathVisitorInfo(resourceProvider ResourceProvider, resourceType api.ResourceType, path api.UnresolvedPath) *api.PathVisitorInfo
GetPathVisitorInfo returns the path visitor specification for the specified path within the specified resource type to pass to a visitor function. It searches all attribute names in the path registry for the normalized path. GetPathVisitorInfo returns the PathVisitorInfo for the specified path. It searches all attribute names in the path registry, checking the specific resource type across all attributes first, then falling back to ResourceTypeAny. This ensures a specific resource type match always takes priority. The first match provides the base Details (getter/setter invocations). IsNeeded/IsProvided flags and Enricher are collected from all matches. Getter/setter invocations are NOT merged across attribute names because they carry resource-type-specific arguments.
func GetPaths ¶
func GetPaths[T api.Scalar]( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, options *api.FunctionOptions, ) (api.AttributeValueList, error)
GetPaths traverses the specified path patterns of the specified resource types and returns an api.AttributeValueList containing the values and registered information about all of the found attributes matching the path patterns. Use only for int and bool attributes. Use GetStringPaths for string attributes.
func GetPathsAnyType ¶
func GetPathsAnyType( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, dataType api.DataType, neededValuesOnly bool, providedValuesOnly bool, options *api.FunctionOptions, ) (api.AttributeValueList, error)
GetPathsAnyType traverses the specified path patterns of the specified resource types and returns an api.AttributeValueList containing the values and registered information about all of the found attributes matching the path patterns.
func GetRegisteredNeededPaths ¶
func GetRegisteredNeededPaths(resourceProvider ResourceProvider) api.ResourceTypeToPathToVisitorInfoType
GetRegisteredNeededPaths returns a combined registry of all paths marked as IsNeeded across all attributes in the path registry.
func GetRegisteredNeededPathsByProperty ¶ added in v0.1.42
func GetRegisteredNeededPathsByProperty(resourceProvider ResourceProvider, neededRequired []string) api.ResourceTypeToPathToVisitorInfoType
GetRegisteredNeededPathsByProperty returns a combined registry of all paths marked as IsNeeded whose Details.NeededRequired map contains every key listed in neededRequired. Values of those required keys are not checked — only presence. This is useful for finding paths that participate in a particular kind of match (e.g., all resource references via the "ResourceType" key) regardless of whether the current value at the path is a placeholder.
func GetRegisteredNeededStringPaths ¶
func GetRegisteredNeededStringPaths( parsedData gaby.Container, resourceProvider ResourceProvider, options *api.FunctionOptions, ) (api.AttributeValueList, error)
GetRegisteredNeededStringPaths retrieves Needed values by scanning all attributes for paths marked as IsNeeded.
func GetRegisteredProvidedPaths ¶
func GetRegisteredProvidedPaths(resourceProvider ResourceProvider) api.ResourceTypeToPathToVisitorInfoType
GetRegisteredProvidedPaths returns a combined registry of all paths marked as IsProvided across all attributes in the path registry.
func GetRegisteredProvidedStringPaths ¶
func GetRegisteredProvidedStringPaths( parsedData gaby.Container, resourceProvider ResourceProvider, options *api.FunctionOptions, ) (api.AttributeValueList, error)
GetRegisteredProvidedStringPaths retrieves Provided values by scanning all attributes for paths marked as IsProvided. Resources with IgnoreProvided annotation are skipped.
func GetResourceCategoryTypeName ¶
func GetResourceCategoryTypeName(doc *gaby.YamlDoc, resourceProvider ResourceProvider) (api.ResourceCategory, api.ResourceType, api.ResourceName, error)
func GetResourceInfo ¶
func GetResourceInfo(doc *gaby.YamlDoc, resourceProvider ResourceProvider) (*api.ResourceInfo, error)
func GetStringPaths ¶
func GetStringPaths( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, options *api.FunctionOptions, ) (api.AttributeValueList, error)
GetStringPaths traverses the specified path patterns of the specified resource types and returns an api.AttributeValueList containing the values and registered information about all of the found string attributes matching the path patterns. It can also extract fields embedded in strings using registered embedded accessors.
func GetToolchainPath ¶
func GetToolchainPath(rp ResourceProvider) string
func GetVisitorMapForPath ¶
func GetVisitorMapForPath(resourceProvider ResourceProvider, rt api.ResourceType, path api.UnresolvedPath) api.ResourceTypeToPathToVisitorInfoType
GetVisitorMapForPath is used to get visitor info for a resolved path.
func GetVisitorOptions ¶ added in v0.1.15
func GetVisitorOptions(doc *gaby.YamlDoc, resourceProvider ResourceProvider) []string
GetVisitorOptions reads the VisitorOptions value from a YAML document using the resource provider's context path.
func InjectCommentKeys ¶ added in v0.1.25
InjectCommentKeys adds comment entries into a map.
func IsCommentKey ¶ added in v0.1.25
IsCommentKey returns true if the key matches the $comment$TYPE$TARGET pattern where TYPE is head, line, or foot. Equivalent to gaby.IsCommentKey.
func IsEmptyOrPlaceHolder ¶ added in v0.1.25
func IsIntPlaceHolderValue ¶ added in v0.1.32
func IsMultiLineString ¶ added in v0.1.14
IsMultiLineString returns true if the string contains embedded newlines (not just a trailing newline), indicating it is a multi-line string value that may benefit from line-level diffing. YAML scalar serialization via gaby appends a trailing newline, so a single-line value like "alice" becomes "alice\n" — this function correctly returns false for such values.
func IsPatchableString ¶ added in v0.1.14
IsPatchableString returns true if the string may benefit from structured or line-level patching rather than wholesale replacement. This includes:
- Multi-line strings (for line-level text diff)
- JSON objects or arrays (for structural JSON diff)
- Strings with YAML structure (for structural YAML diff)
func IsPlaceholderValue ¶ added in v0.1.32
IsPlaceholderValue returns true if the value is a placeholder that should be replaced with a default.
func IsStringPlaceHolderValue ¶ added in v0.1.32
func JoinPathSegments ¶
JoinPathSegments escapes any dots in path segments and joins them for use in whole-path searches.
func JoinRelativePath ¶ added in v0.4.8
JoinRelativePath joins a relative path to the prefix it sits under. Either may be empty.
func LeadingWhitespace ¶ added in v0.1.25
LeadingWhitespace returns the leading whitespace prefix of a line.
func LowerFirst ¶
LowerFirst lowercases the first character, which is useful for converting PascalCase to camelCase
func MarshalSpecSet ¶ added in v0.4.8
MarshalSpecSet renders a spec set as YAML, the form LoadSpecSet reads.
func MatchesWhereResourceExpressions ¶
func MatchesWhereResourceExpressions(doc *gaby.YamlDoc, resourceInfo *api.ResourceInfo, expressions []*api.VisitorRelationalExpression) (bool, error)
MatchesWhereResourceExpressions evaluates each expression against a resource. For paths with the "ConfigHub." prefix, values are resolved from ResourceInfo metadata. For other paths, values are resolved from the resource's YAML document using YamlSafePathGetValueAnyType. Returns false if any expression doesn't match. Keep consistent with ValidWhereResourcePaths.
func MergeCommentsIntoData ¶ added in v0.1.25
MergeCommentsIntoData walks a parsed data tree and inserts comment keys at the corresponding map levels based on a flat comment map. The flat map uses dot-separated paths to indicate where in the nested structure the comment belongs. For example, "database.$comment$head$server" places the comment key "$comment$head$server" inside the "database" map.
func MergeKeyIdentity ¶ added in v0.2.12
MergeKeyIdentity joins merge-key values into the single string used to match an element between two revisions and to record array ordering.
func MergeKeyValues ¶ added in v0.2.12
MergeKeyValues returns the merge-key values of an array element, in the order of keys. It reports false when the element is missing any of them, or when a value contains a character the path segment uses as punctuation: either way the element has no usable identity and the caller falls back to matching it by position.
func NameArrayElementsByMergeKey ¶ added in v0.2.22
func NameArrayElementsByMergeKey(doc *gaby.YamlDoc, path api.ResolvedPath, mergeKeyLookup MergeKeyLookup) (api.ResolvedPath, bool)
NameArrayElementsByMergeKey rewrites the bare numeric segments of a path into associative segments naming each element by its merge keys, resolved against doc. It is the inverse of what ResolveAssociativeSegments does, and reports whether anything changed.
It exists for the records written before the associative encoding did. An entry that says containers.0.image names whatever is first in line rather than the container, so it drifts with every insertion ahead of it, and no string rewrite can repair that: recovering the element's identity needs the document the entry was computed against, which only the caller can supply.
A segment is left numeric when the array declares no merge keys, when the element does not carry them, or when the document has nothing at that position. Positional resolution still works for such a path, which is what makes leaving it alone the safe answer rather than a failure. Segments are resolved against the path as it arrived, so a rewrite that could not be made never costs the ones after it.
func NormalizeStructurePath ¶ added in v0.4.8
NormalizeStructurePath replaces numeric array indices and associative segments in a dot-separated path with "*", which is the form the structure lookups are keyed by.
This is deliberately narrower than normalizePath: the structure lookups are what decide whether a segment is a dynamic map key in the first place, so consulting them here would make their key function depend on their contents.
func PatchMutations ¶
func PatchMutations(parsedData gaby.Container, mutationsProtection, mutationsPatch, mutationsToSubtract api.ResourceMutationList, resourceProvider ResourceProvider, options *api.FunctionOptions) (gaby.Container, api.MutationConflictList, error)
PatchMutations applies a patch with no guard filtering. Equivalent to PatchMutationsGuarded with no filter, and the form every caller that predates guards uses.
func PatchMutationsGuarded ¶ added in v0.2.22
func PatchMutationsGuarded(parsedData gaby.Container, mutationsProtection, mutationsPatch, mutationsToSubtract api.ResourceMutationList, guards *GuardFilter, resourceProvider ResourceProvider, options *api.FunctionOptions) (gaby.Container, api.MutationConflictList, error)
PatchMutationsGuarded is PatchMutations with the guard filter applied: a path whose guards the operation's clearance does not cover is not written, and the withheld change is reported as a ConflictReasonGuarded carrying the guard that stopped it.
The guard check sits beside the protection check rather than replacing it. The two say different things -- protection says the target claimed a path and gives no reason, a guard names the reason and can be cleared by an operation that knows it -- and Protected does not migrate onto a guard key until guards carry the traffic.
func PathIsResolved ¶
func RegisterAttributeGroup ¶ added in v0.4.8
func RegisterAttributeGroup( resourceProvider ResourceProvider, groupName api.AttributeName, members ...api.AttributeName, )
RegisterAttributeGroup declares that one attribute name stands for the union of others, so a function reading it through GetPathRegistryForAttributeName sees every member's paths. The group itself owns no paths and appears in no spec; it exists so attributes that must be distinguishable when written can still be read together.
func RegisterDeclaredAttributePaths ¶ added in v0.4.8
func RegisterDeclaredAttributePaths( resourceProvider ResourceProvider, compiled *CompiledSpecs, toolchainType workerapi.ToolchainType, descriptors map[api.AttributeName]AttributeDescriptor, enrich PathEnricher, ) error
RegisterDeclaredAttributePaths registers every attribute path the compiled specs declare for a toolchain, pairing each with the descriptor registered for its attribute name. It is the data-driven replacement for hand-rolled loops over per-concern tables.
Registration order is deterministic: resource types and attribute names are both sorted, so two runs of the same specs produce the same registry.
func RegisterPathsByAttributeName ¶
func RegisterPathsByAttributeName( resourceProvider ResourceProvider, attributeName api.AttributeName, resourceType api.ResourceType, pathInfos api.PathToVisitorInfoType, details *AttributeRegistrationDetails, isNeeded bool, isProvided bool, )
RegisterPathsByAttributeName registers the specified path visitor specifications under the designated attribute name and resource type, and adds the provided getter and setter invocations, merging with existing registrations at the same paths, if any. If requested, the registered paths will be normalized so that associative lookups and array indices will be converted to wildcards, which is desired when matching all paths to the attribute. AttributeNameResourceName is used for references to resource names. Other attribute names are used for specific setters and/or getters, especially for attributes that appear in multiple resource types and/or locations. Provided values are special in that they represent sources of values for attributes of the specified attribute name, though they are logically distinct kinds of attributes.
func ReplaceStringPlaceholder ¶ added in v0.1.76
ReplaceStringPlaceholder replaces all occurrences of the placeholder string PlaceHolderBlockApplyString in s with replacement, including named placeholders that consist of the placeholder string followed by additional alphabetic characters. Surrounding text is preserved, so "confighubplaceholder-http" becomes replacement + "-http" and "confighubplaceholdersubdomain.test.example.com" becomes replacement + ".test.example.com".
func Reset ¶
func Reset(parsedData gaby.Container, mutationsProtection api.ResourceMutationList, resourceProvider ResourceProvider, options *api.FunctionOptions) error
Reset walks each path in mutationsProtection and, where Protected is false and the value at the corresponding location in parsedData is a string or int, sets the value back to the toolchain's placeholder marker (PlaceHolderBlockApplyString / PlaceHolderBlockApplyInt). Used by the "reset" function to revert the leaves last touched by a chosen subset of historical mutations to their unset state, leaving everything else alone.
func ResolveAssociativeSegments ¶
ResolveAssociativeSegments resolves ?key=value;@index segments in a path to numeric indices by looking up elements in the document. An array whose elements are identified by more than one field carries one pair per key — ?key1=value1,key2=value2;@index — and an element matches only when it has all of them. If no element matches, it considers the positional index:
- Out of bounds: the index is used as-is. This preserves Add-as-append semantics (e.g., a new element being appended to an array) and is harmless for Delete since the caller checks existence before deleting.
- In bounds, element has no merge-key field: legacy data — fall back positionally.
- In bounds, element has a different merge-key value: a different element. The segment is left unresolved so the caller can skip the operation.
Returns the resolved path and a bool that is true only when every associative segment was resolved (by merge-key match, by out-of-bounds index, or by legacy fallback).
func ResolveAssociativeSegmentsForInsertion ¶ added in v0.2.22
ResolveAssociativeSegmentsForInsertion is ResolveAssociativeSegments for the path of an element a patch adds to a positional array, whose last segment is an anchor.
The anchor on such a segment digests the element the patch is about to create, not one to go looking for. Matching it against the target finds an element that merely has the same content — a repeated argument, a duplicated list entry — and puts the new element beside that one instead of at the position the patch named. So the last segment keeps its recorded index, which is the only thing that says where an insertion goes. Everything ahead of it is a path to an element that does exist, and resolves as usual.
func ResolveConfigHubPath ¶ added in v0.1.28
func ResolveConfigHubPath(path string, resourceInfo *api.ResourceInfo) (any, error)
ResolveConfigHubPath resolves a ConfigHub.* metadata path against a ResourceInfo struct. Returns the resolved value, or an error if the path is unsupported. Keep consistent with ValidWhereResourcePaths in api.go.
func ResourceAndCategoryTypeMaps ¶
func ResourceAndCategoryTypeMaps(parsedData gaby.Container, resourceProvider ResourceProvider) ( resourceMap ResourceNameToCategoryTypesMap, categoryTypeMap ResourceCategoryTypeToNamesMap, err error, )
ResourceAndCategoryTypeMaps returns maps of all resources in the provided list of parsed YAML documents, from from names to categories+types and categories+types to names.
func ResourceTypesForAttribute ¶
func ResourceTypesForAttribute(attributeName api.AttributeName, resourceProvider ResourceProvider) []api.ResourceType
ResourceTypesForAttribute returns a list of resource types associated with the specified attribute.
func ResourceTypesForPathMap ¶
func ResourceTypesForPathMap(pathMap map[api.ResourceType][]string) []api.ResourceType
ResourceTypesForPathMap returns a list of resource types from a path map.
func SetProtection ¶ added in v0.2.15
func SetProtection(parsedData gaby.Container, mutations api.ResourceMutationList, resource api.ResourceInfo, protection map[api.ResolvedPath]bool, resourceProvider ResourceProvider) (api.ResourceMutationList, []api.ResolvedPath)
SetProtection sets the Protected flag on path-level mutations of a single resource in mutations (typically a Unit's accumulated MutationSources), returning the updated list and the paths that could not be resolved.
The Protected flag records whether the path is a local override a merge must not overwrite: true protects it, false leaves it the merge's to update. A merge consumes these stored values, so editing them changes what a subsequent upgrade/merge will overwrite.
For each (path, value) in protection:
- Exact match: the entry at path has its Protected set to value; its other fields (including Value) are left intact.
- No exact match: the closest ancestor present in the resource's PathMutationMap (or, failing that, the resource-level mutation) supplies the MutationType and Index, so the new, more-specific entry keeps the same provenance. The entry's Value is taken from the data at path (via YamlSafePathGetDoc) — NOT copied from the ancestor, whose Value is a broader block — and Patch is left empty (it is a line-diff that does not apply to a freshly-set value). Because the protection lookup during PatchMutations walks to the most specific ancestor, this scopes the setting to path without disturbing the ancestor. This mirrors the parent-splitting in SubtractMutations' Case 3.
A path is returned in unresolved (and left unchanged) when its resource is absent, when it has neither an ancestor path nor a resource-level mutation to inherit from, or when it does not exist in the resource's data (so no Value can be extracted). parsedData and resourceProvider are used to locate the resource's document and read the value at each path. mutations is modified in place and also returned for convenience.
func SplitInlineComment ¶ added in v0.1.25
SplitInlineComment splits a value string into the clean value and inline comment. An inline comment is text after " #" (space-hash). Quoted values are not split. Returns the clean value and the comment text (without the # prefix). If there is no inline comment, comment is empty.
func StoredMutationPathsNeedRewriting ¶ added in v0.4.10
func StoredMutationPathsNeedRewriting(mutations api.ResourceMutationList, resourceProvider ResourceProvider) bool
StoredMutationPathsNeedRewriting reports whether CanonicalizeStoredMutationPaths would have anything to do, without a document. It is the same question the canonicalization asks first, exported for a caller holding a record whose configuration data is not parsed yet: parsing it to discover there is nothing to rewrite is the cost worth avoiding.
func StripAssociativeSegments ¶
StripAssociativeSegments converts ?key=value;@index segments to just the numeric index. For ?key=@index (direct index), extracts just the index. Non-associative segments are passed through as-is.
func StripCommentKeys ¶ added in v0.1.25
StripCommentKeys returns a deep copy of data with all comment keys removed. Works recursively on map[string]any and []any. Non-map, non-slice values are returned as-is.
func StripComments ¶
StripComments removes all comments from YAML data while preserving the structure and values. This is useful when comparing YAML documents where comments should be ignored.
func SubtractMutations ¶
func SubtractMutations(mutations, subtractMutations api.ResourceMutationList) (api.ResourceMutationList, api.MutationConflictList)
SubtractMutations removes from mutations any changes that overlap with subtractMutations, implementing the "preserve target-side changes" half of three-way merging. Typically invoked from PatchMutations via its mutationsToSubtract argument.
Use case:
source : ComputeMutations(base, sourceEnd) // upstream changes target : ComputeMutations(base, target) // local customizations patch : SubtractMutations(source, target) // source changes that don't conflict
When PatchMutations applies patch to target, target-side customizations remain because the source paths that would have overwritten them have been removed.
Both operands are expected to be diffs produced by ComputeMutations: Add, Delete, Update, or None at the resource level. (Replace, which AddMutations may produce when accumulating, is handled here defensively but not expected.) Update at the resource level has an empty Value — all changes live in PathMutationMap.
Algorithm:
Resource matching: by ResourceTypeAndName, then AliasesWithoutScopes from either side (so renamed resources subtract correctly).
Resource-level subtraction:
| Subtract Type | Mutation Type | Result | |---------------|---------------|-------------------------------------------------| | Delete | Any | Drop (target removed the resource) | | Replace | Any | Drop (target redefined the resource) | | None | Any | Keep (target didn't change it) | | Any | None | Keep (source didn't change it) | | Update/Add | Delete | Keep source Delete; emit DeleteShadowed for | | | | each target mutation under it (the target's | | | | edits have nowhere to live once the resource | | | | is gone) | | Update/Add | Update/Add | Path-level subtraction |
Path-level subtraction: paths are walked using a NewPathPrefixIndex (binary search over a sorted path list) so prefix relationships are O(log n + k):
- Case 1 (exact match): subtract has the same path → drop the source path. - Case 2 (subtract is ancestor): subtract has spec.containers.0 and source has spec.containers.0.image → drop the source path (parent was changed in target). - Case 3 (subtract is descendant): subtract has spec.containers.0.image and source has spec.containers.0 (whole block). If the source path is a Delete, keep it and emit a DeleteShadowed conflict for each target child path that's being erased — once the parent is gone the child changes can't apply. Otherwise keep the source path and splice in subtract's more-specific paths so PatchMutations' parent-before-child processing lets target's change win.
If subtraction empties an Update's PathMutationMap, the resource-level type downgrades to None.
Returns the patch with subtractions applied, plus a MutationConflictList recording every drop (resource-level and path-level) so callers can surface them as merge conflicts. The conflicts are advisory — the returned ResourceMutationList already reflects the drops.
Key behaviors:
- Target precedence: subtractMutations always wins where it overlaps.
- Alias awareness: matches resources across renames.
- Partial expansion: only splits a parent path when subtract has finer-grained conflicts under it; unaffected branches stay whole.
func TransformConfig ¶
func TransformConfig( originalData []byte, resourceProvider ResourceProvider, transform func(parsedData gaby.Container) ([]byte, error), options *api.FunctionOptions, ) ([]byte, bool, error)
TransformConfig applies a mutation function to configuration data, preserving YAML comments by diffing the changes and patching them onto the original data. This is a general-purpose mechanism that can be reused for any config transformation that operates on comment-stripped data (Starlark, CEL, etc.).
The transform function receives comment-stripped parsed YAML and returns modified YAML bytes. If the transform function returns nil bytes, the original data is returned unchanged.
func UpdatePathsFunction ¶
func UpdatePathsFunction[T api.Scalar]( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, updater func(T, VisitorContext) T, upsert bool, options *api.FunctionOptions, ) error
UpdatePathsFunction traverses the specified path patterns of the specified resource types. The updater function simply needs to return the new attribute value, which must be of the type of the generic type parameter.
func UpdatePathsFunctionDoc ¶
func UpdatePathsFunctionDoc( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, updater func(*gaby.YamlDoc, VisitorContext) *gaby.YamlDoc, upsert bool, options *api.FunctionOptions, ) error
UpdatePathsFunctionDoc traverses the specified path patterns of the specified resource types. The updater function simply needs to return the new attribute value, which must be a YamlDoc.
func UpdatePathsSetterArgument ¶
func UpdatePathsSetterArgument( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, upsert bool, options *api.FunctionOptions, ) error
UpdatePathsSetterArgument traverses the specified path patterns of the specified resource types. For each path whose Details carry a DefaultValue, the value at the path is set to it. Supports string, int, and bool values. Skips paths where the current value is already set to a non-placeholder value. Otherwise, the path is not updated.
func UpdatePathsValue ¶
func UpdatePathsValue[T api.Scalar]( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, newValue T, upsert bool, options *api.FunctionOptions, ) error
UpdatePathsValue traverses the specified path patterns of the specified resource types and updates the attributes with the provided value.
func UpdateStringPaths ¶
func UpdateStringPaths( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, newValue string, upsert bool, options *api.FunctionOptions, ) error
UpdateStringPaths traverses the specified path patterns of the specified resource types and updates the attributes with the provided value. It can also inject fields embedded in strings using registered embedded accessors.
func UpdateStringPathsFunction ¶
func UpdateStringPathsFunction( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, updater func(string) string, upsert bool, options *api.FunctionOptions, ) error
UpdateStringPathsFunction traverses the specified path patterns of the specified resource types. The updater function simply needs to return the new attribute value. It can also inject fields embedded in strings using registered embedded accessors.
func VetPathsSetterArgument ¶
func VetPathsSetterArgument( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, resourceProvider ResourceProvider, options *api.FunctionOptions, ) (api.ValidationResult, error)
VetPathsSetterArgument traverses the specified path patterns and validates that current values match the DefaultValue their Details carry. Returns a ValidationResult with Passed=false and FailedAttributes listing any mismatched paths.
func VisitPaths ¶
func VisitPaths[T api.Scalar]( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, output any, resourceProvider ResourceProvider, visitor VisitorFunc[T], upsert bool, options *api.FunctionOptions, ) (any, error)
VisitPaths is a simple wrapper of the base visitor function. It traverses the specified path patterns of the specified resource types within the parsed configuration YAML document list.
func VisitPathsAnyType ¶
func VisitPathsAnyType( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, output any, resourceProvider ResourceProvider, visitor VisitorFuncAnyType, upsert bool, options *api.FunctionOptions, ) (any, error)
VisitPathsAnyType is a simple wrapper of the base visitor function. It traverses the specified path patterns of the specified resource types within the parsed configuration YAML document list.
func VisitPathsDoc ¶
func VisitPathsDoc( parsedData gaby.Container, resourceTypeToPaths api.ResourceTypeToPathToVisitorInfoType, keys []any, output any, resourceProvider ResourceProvider, visitor VisitorFuncDoc, upsert bool, options *api.FunctionOptions, ) (any, error)
VisitPathsDoc is the base visitor function. It traverses the specified path patterns of the specified resource types within the parsed configuration YAML document list.
func VisitResources ¶
func VisitResources(parsedData gaby.Container, output any, resourceProvider ResourceProvider, visitor ResourceVisitorFunc) (any, error)
VisitResources iterates over all of the resources/elements in a configuration unit and passes metadata about the resource as well as the document itself to a visitor function.
func VisitResourcesFiltered ¶
func VisitResourcesFiltered(parsedData gaby.Container, output any, resourceProvider ResourceProvider, options *api.FunctionOptions, visitor ResourceVisitorFunc) (any, error)
VisitResourcesFiltered iterates over resources, skipping those that don't match the WhereResourceExpressions in options or that fall outside its ResourceIndexes. The two restrictions are AND-ed. When options has neither, it behaves identically to VisitResources.
func VisitorInfoEqual ¶
func VisitorInfoEqual(pathVisitorInfo1, pathVisitorInfo2 *api.PathVisitorInfo) bool
VisitorInfoEqual reports whether two path visitor specifications, optionally including getter and setter invocations, match.
func YamlSafePathGetDoc ¶
func YamlSafePathGetDoc( doc *gaby.YamlDoc, resolvedPath api.ResolvedPath, notFoundOk bool, ) (*gaby.YamlDoc, bool, error)
YamlSafePathGetDoc returns a document node at a fully resolved path and whether it was found. An error indicates a parsing error. An error is also returned if the path is expected to exist.
func YamlSafePathGetValue ¶
func YamlSafePathGetValue[T api.Scalar]( doc *gaby.YamlDoc, resolvedPath api.ResolvedPath, notFoundOk bool, ) (T, bool, error)
YamlSafePathGetValue returns a value at a fully resolved path and whether it was found. An error indicates a parsing error or that the value was not of the expected type.
func YamlSafePathGetValueAnyType ¶
func YamlSafePathGetValueAnyType( doc *gaby.YamlDoc, resolvedPath api.ResolvedPath, notFoundOk bool, ) (any, bool, error)
YamlSafePathGetValueAnyType returns a value at a fully resolved path and whether it was found. An error indicates a parsing error.
Types ¶
type AttributeDescriptor ¶ added in v0.4.8
type AttributeDescriptor struct {
// DataType is the default for declared paths that do not state one of their own. An
// attribute may hold paths of more than one type, so this is a default and not a
// constraint.
DataType api.DataType
EmbeddedAccessorType api.EmbeddedAccessorType
EmbeddedAccessorConfig string
api.AttributeNeedsProvidesDetails
Enricher AttributeEnricher
IsNeeded bool
IsProvided bool
// Derived names attributes registered at a suffix of every path declared for this one.
// A hostname declares one path; the subdomain and the domain within it are read through
// embedded accessors at "<path>#subdomain" and "<path>#domain", and a type that has a
// hostname always has both. Declaring the suffix once beats declaring three paths per
// type that have to be kept in step. Each derived attribute has its own descriptor, so it
// carries its own accessor, getter and setter.
Derived []DerivedAttribute
// DescribePaths asks the toolchain's PathEnricher for a description of each declared path,
// from whatever schema it has. It is per attribute because it is a real cost -- a schema
// lookup per path at registration -- and not every attribute wants it: nothing reads the
// value at an immutable path, so describing one buys nothing.
DescribePaths bool
}
AttributeDescriptor is everything about an attribute that does not vary by resource type: what the value is, how to read and write it, and how it is recorded. Specs say where an attribute lives; this says what it is. It stays in Go because getters and setters are Go.
type AttributeEnricher ¶ added in v0.1.15
AttributeEnricher is a function that enriches an AttributeValue with properties after it is extracted by a visitor. It receives the resource doc for context and a flag indicating whether the value is a provided value. It populates ProvidedProperties, NeededRequired, and/or NeededPreferred on the attribute's Details.
type AttributePath ¶ added in v0.4.8
type AttributePath struct {
Path string `json:"path"`
DataType api.DataType `json:"dataType,omitempty"`
// Default is the value a defaulting function writes here, for attributes that carry one.
// It is per path rather than per attribute because the whole point of a defaulting
// attribute is that each of its paths gets a different value; the descriptor cannot hold
// it. A path with a Default registers a visitor setter carrying that value.
Default any `json:"default,omitempty"`
// Needed and Provided override the descriptor's flags for this path alone, for an
// attribute whose paths do not all play the same role. configmap-hash is the case: a
// ConfigMap's own annotation offers the hash and a pod template's wants it, under one
// attribute name, and a descriptor carries one pair of flags for every path under it.
Needed bool `json:"needed,omitempty"`
Provided bool `json:"provided,omitempty"`
// Target is the resource type this path names, for a path that refers to another
// resource: a Rollout's spec.strategy.canary.stableService names a v1/Service. It
// compiles to the ResourceType property that needs and provides matching selects on,
// and fills the target parameter of the attribute's getter and setter.
//
// Like Default it is per path and not per attribute, for the same reason: a type's
// reference paths point at different types, so the descriptor cannot hold it.
Target api.ResourceType `json:"target,omitempty"`
}
AttributePath is one location of an attribute within a resource type or shape, relative to whatever root the declaration sits at. Everything else about the attribute -- its data type, getter, setter, embedded accessor -- comes from the descriptor registered once per attribute name, because none of it varies by resource type. What varies is only where the attribute lives, which is what a spec says.
DataType overrides the descriptor's for this path alone. An attribute may hold paths of more than one data type; the descriptor's is the default, not a constraint the paths must match.
type AttributeRegistrationDetails ¶ added in v0.1.15
type AttributeRegistrationDetails struct {
api.AttributeNeedsProvidesDetails
Enricher AttributeEnricher
}
AttributeRegistrationDetails specifies getter/setter invocations and an optional Enricher function for use when registering paths via RegisterPathsByAttributeName.
type CommentType ¶ added in v0.1.25
type CommentType string
CommentType represents the position of a comment relative to its anchor element.
const ( // CommentHead is a comment that appears on the line(s) above its anchor. CommentHead CommentType = "head" // CommentLine is an inline comment on the same line as its anchor. CommentLine CommentType = "line" // CommentFoot is a comment that appears on the line(s) below its anchor. CommentFoot CommentType = "foot" )
func ParseCommentKey ¶ added in v0.1.25
func ParseCommentKey(key string) (CommentType, string, bool)
ParseCommentKey extracts the comment type and target key from a comment map key. Returns ("", "", false) if the key is not a comment key.
type CompiledSpecs ¶ added in v0.4.8
type CompiledSpecs struct {
// contains filtered or unexported fields
}
CompiledSpecs is the immutable result of compiling spec sets: the structure lookups the merge engine reads, with every embed expanded and every relative path joined to where it sits.
It is built during construction and read-only afterwards. Reads are on the merge hot path and are two map lookups, as they were when the lookups were package globals.
func CompileSpecSets ¶ added in v0.4.8
func CompileSpecSets(sets ...SpecSet) (*CompiledSpecs, error)
CompileSpecSets compiles spec sets into one immutable snapshot. Shapes are resolved across all the sets together, so a set registering a new type can embed a shape another set declares -- a CRD carrying an ordinary PodSpec is the case that needs it. A shape name declared twice is an error rather than a silent win for whichever set was passed last.
func (*CompiledSpecs) ApplyPriorityOf ¶ added in v0.4.10
func (c *CompiledSpecs) ApplyPriorityOf(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) (int, bool)
ApplyPriorityOf returns the apply priority a type declares, and whether it declares one.
func (*CompiledSpecs) DeclaredAttributes ¶ added in v0.4.8
func (c *CompiledSpecs) DeclaredAttributes( toolchainType workerapi.ToolchainType, resourceType api.ResourceType, ) map[api.AttributeName][]AttributePath
DeclaredAttributes returns the attribute paths declared for one resource type of one toolchain, keyed by attribute name, with every embed expanded and every relative path joined to where it sits. The returned slices are the compiled snapshot's own and must not be modified.
func (*CompiledSpecs) ExclusiveFieldsForPath ¶ added in v0.4.8
func (c *CompiledSpecs) ExclusiveFieldsForPath( toolchainType workerapi.ToolchainType, resourceType api.ResourceType, path string, ) (ExclusiveFields, bool)
ExclusiveFieldsForPath returns the mutually exclusive sibling fields of the object at the given path, checking the type's own entries before those declared for api.ResourceTypeAny.
The table this replaced had no wildcard fallback, unlike the merge-key and map-key tables beside it. Nothing declares a wildcard union today, so adding it changes no answer; it means the first one declared works rather than being silently ignored for every type.
func (*CompiledSpecs) IsMapKeyPath ¶ added in v0.4.8
func (c *CompiledSpecs) IsMapKeyPath( toolchainType workerapi.ToolchainType, resourceType api.ResourceType, path string, ) bool
IsMapKeyPath reports whether the path is a freeform map whose children are dynamic keys (label keys, annotation keys) rather than schema-defined fields. Child segments of such a path are wildcarded during normalization. The path should end with ".*" to ask about a map's children.
func (*CompiledSpecs) MergeKeysForPath ¶ added in v0.4.8
func (c *CompiledSpecs) MergeKeysForPath( toolchainType workerapi.ToolchainType, resourceType api.ResourceType, path string, ) ([]string, bool)
MergeKeysForPath returns the merge key field names for the given resource type and array path, checking the type's own entries before those declared for api.ResourceTypeAny.
func (*CompiledSpecs) ReferencePaths ¶ added in v0.4.8
func (c *CompiledSpecs) ReferencePaths(toolchainType workerapi.ToolchainType) []DeclaredReference
ReferencePaths returns every declared attribute path carrying a Target, sorted by resource type, then attribute name, then path, then target. A path that several targets are declared for -- a field naming any of three workload controllers -- appears once per target, which is how the requirement is registered and how it is unioned.
Sorted because a registry assembled by ranging over maps differs run to run, and it is served that way on a function server's /paths route.
func (*CompiledSpecs) RenderAttributes ¶ added in v0.4.8
func (c *CompiledSpecs) RenderAttributes(toolchainType workerapi.ToolchainType) string
RenderAttributes writes every attribute path declared for one toolchain in a stable order, as tab-separated lines. It is the attribute counterpart of RenderStructure, and exists for the same reason: an attribute that never reaches the path registry -- one whose paths are handed straight to a visitor -- is covered by no other capture.
func (*CompiledSpecs) RenderStructure ¶ added in v0.4.8
func (c *CompiledSpecs) RenderStructure(toolchainType workerapi.ToolchainType) string
RenderStructure writes every structure entry compiled for one toolchain in a stable order, as tab-separated lines. It is the enumeration the compiled snapshot otherwise has no read surface for -- MergeKeysForPath and its siblings are point queries -- and exists so a differential test can compare a whole snapshot rather than the paths someone thought to ask about.
func (*CompiledSpecs) ResourceTypesEmbeddingShape ¶ added in v0.4.8
func (c *CompiledSpecs) ResourceTypesEmbeddingShape( toolchainType workerapi.ToolchainType, shapeName string, ) []api.ResourceType
ResourceTypesEmbeddingShape returns every resource type embedding the named shape, sorted.
func (*CompiledSpecs) ResourceTypesWithAttributes ¶ added in v0.4.8
func (c *CompiledSpecs) ResourceTypesWithAttributes(toolchainType workerapi.ToolchainType) []api.ResourceType
ResourceTypesWithAttributes returns every resource type declaring at least one attribute for the toolchain, sorted, so registration is deterministic.
func (*CompiledSpecs) ResourceTypesWithScope ¶ added in v0.4.10
func (c *CompiledSpecs) ResourceTypesWithScope(toolchainType workerapi.ToolchainType, scope Scope) []api.ResourceType
ResourceTypesWithScope returns every type declaring the given scope, sorted.
func (*CompiledSpecs) SchemaFor ¶ added in v0.4.10
func (c *CompiledSpecs) SchemaFor(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) string
SchemaFor returns what a type declares about where its own schema is: a location that overrides the toolchain's templates, SchemaNone for a type known to have none, or "" for the ordinary case of "look where the templates say".
func (*CompiledSpecs) SchemaLocationsFor ¶ added in v0.4.10
func (c *CompiledSpecs) SchemaLocationsFor(toolchainType workerapi.ToolchainType) []string
SchemaLocationsFor returns where a toolchain's schemas are fetched from, most authoritative first, as templates over the resource type. Empty for a toolchain that declares none, which is every toolchain whose formats have no schema to fetch.
func (*CompiledSpecs) ScopeOf ¶ added in v0.4.10
func (c *CompiledSpecs) ScopeOf(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) Scope
ScopeOf returns the scope a type declares, or "" if it declares none.
func (*CompiledSpecs) ShapePaths ¶ added in v0.4.8
func (c *CompiledSpecs) ShapePaths( toolchainType workerapi.ToolchainType, resourceType api.ResourceType, shapeName string, ) []string
ShapePaths returns where a shape sits within a resource type, in declaration order, or nil if the type does not embed it. A type embedding a shape more than once -- three container arrays under one PodSpec -- gets one entry per embed.
func (*CompiledSpecs) SimilarityClassOf ¶ added in v0.4.10
func (c *CompiledSpecs) SimilarityClassOf(toolchainType workerapi.ToolchainType, resourceType api.ResourceType) string
SimilarityClassOf returns the similarity class a type declares, or "" if it declares none. Two types are similar when both declare the same non-empty class.
type Declaration ¶ added in v0.4.8
type Declaration struct {
// Embeds places shapes within this declaration.
Embeds []ShapeEmbed `json:"embeds,omitempty"`
// What the merge engine reads, before any path is normalized. These are inputs to the
// path registry's key function rather than entries in it, which is why they are not
// attributes.
MergeKeys []MergeKeyField `json:"mergeKeys,omitempty"`
ExclusiveFields []ExclusiveFieldGroup `json:"exclusiveFields,omitempty"`
// MapKeyPaths name the freeform maps whose children are dynamic keys rather than schema
// fields -- a labels map, an annotations map. Each must end in ".*", because the question
// normalizePath asks is always "is the thing to my left a map, so my next segment is a
// key?", and it asks it with a path ending in the wildcard. A path without that suffix can
// never match one and is silently dead; CompileSpecSets rejects it rather than accepting a
// declaration that does nothing.
MapKeyPaths []string `json:"mapKeyPaths,omitempty"`
// Attributes: what the functions read, keyed by attribute name. This is the path registry
// transposed -- indexed by resource type rather than by concern -- so registering a type
// is one edit rather than one edit per attribute the type has.
Attributes map[api.AttributeName][]AttributePath `json:"attributes,omitempty"`
}
Declaration is the body a shape and a resource-type spec share: structure facts with every path stated relative to the root the declaration sits at. A spec's root is the resource; a shape's root is wherever it is embedded.
type DeclaredReference ¶ added in v0.4.8
type DeclaredReference struct {
ResourceType api.ResourceType
AttributeName api.AttributeName
Path string
Target api.ResourceType
}
DeclaredReference is one path that names another resource: which type declares it, where the path is, what attribute it is a path of, and which type it points at.
type DerivedAttribute ¶ added in v0.4.8
type DerivedAttribute struct {
AttributeName api.AttributeName
PathSuffix string
}
DerivedAttribute is an attribute registered at a suffix of another attribute's paths.
type EmbeddedAccessor ¶
type EmbeddedAccessor interface {
// ExistsP reports whether the specified attribute or subpart exists within
// the string at the specified YAML document node.
ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
// SetP sets the specified attribute or subpart within the string at the
// specified YAML document node.
SetP(scalarYamlDoc *gaby.YamlDoc, value any, path string) error
// Data returns the value of the specified attribute or subpart embedded
// within the string at the specified YAML document node.
Data(scalarYamlDoc *gaby.YamlDoc, path string) (any, error)
// Replace replaces the value of the specified attribute or subpart within
// the provided string.
Replace(currentFieldValue string, value any, path string) (string, error)
// Extract returns the value of the specified attribute or subpart within the
// provided string.
Extract(currentFieldValue, path string) (any, error)
}
EmbeddedAccessor is used to access attributes embedded in data formats encoded within string values within a YAML document. For instance, YAML might be encoded within a YAML value. Or it could be as simple as a structured string with distinct sections and separators, such as a container image or URL.
func GetEmbeddedAccessor ¶
func GetEmbeddedAccessor(embeddedAccessorType api.EmbeddedAccessorType, config string) (EmbeddedAccessor, error)
type ExactValueMatcher ¶ added in v0.1.76
type ExactValueMatcher struct {
Value any
}
ExactValueMatcher matches values that are equal to Value. It is used for non-string values such as the integer placeholder, where substring or regular expression matching does not apply.
func (ExactValueMatcher) Matches ¶ added in v0.1.76
func (m ExactValueMatcher) Matches(value any) bool
type ExclusiveFieldGroup ¶ added in v0.4.8
type ExclusiveFieldGroup struct {
Path string `json:"path"`
Members []string `json:"members"`
Discriminator string `json:"discriminator,omitempty"`
AllowedMember map[string]string `json:"allowedMember,omitempty"`
}
ExclusiveFieldGroup declares a set of sibling fields of which at most one may be present, at a path relative to whatever root the declaration sits at.
Path is the dot-separated path to the object holding them, with "*" for any array index. Members are the mutually exclusive fields. Discriminator names the sibling that says which member is valid, where the schema has one, and AllowedMember maps each of its values to the member it permits -- a value with no entry permits none.
This is Kubernetes' patchStrategy:"retainKeys" expressed as data. The API server rejects a resource with two members set, so a merge that adds one member and cannot remove the other produces configuration that will not apply.
type ExclusiveFields ¶ added in v0.2.13
type ExclusiveFields struct {
Members []string
Discriminator string
AllowedMember map[string]string
}
ExclusiveFields describes a set of sibling fields of which at most one may be present — a union, in the schema sense.
Discriminator names the sibling that says which member is valid, where the schema has one: a Deployment's strategy has `type`, and `rollingUpdate` is only permitted when it reads RollingUpdate. AllowedMember maps each discriminator value to the member it permits; a value with no entry permits none. Where there is no discriminator — a Volume's source is an inline union with nothing naming it — Discriminator is empty and the member the patch sets is the one that survives.
func (ExclusiveFields) IsMember ¶ added in v0.2.13
func (e ExclusiveFields) IsMember(field string) bool
IsMember reports whether a field name is one of the union's members.
type ExclusiveFieldsLookup ¶ added in v0.2.13
type ExclusiveFieldsLookup func(path string) (ExclusiveFields, bool)
ExclusiveFieldsLookup is ExclusiveFieldsForPath bound to one resource type.
type GuardFilter ¶ added in v0.2.22
type GuardFilter struct {
Annotations api.PathAnnotationList
Clearance api.Clearance
}
GuardFilter is what an operation brings to a patch about guards: the target's annotation table, and the clearance the operation carries. Both are needed together -- a table with no clearance withholds every guarded write, and a clearance with no table has nothing to clear.
A nil filter, or one whose table holds no annotations, costs nothing: the guard check is skipped entirely, which is the state every Unit is in until someone guards something.
type JSONAccessor ¶ added in v0.1.14
type JSONAccessor struct{}
JSONAccessor is an EmbeddedAccessor that accesses fields within a JSON string value embedded in a YAML scalar. The path uses dot-separated segments to navigate the parsed JSON structure.
For example, given a YAML field containing the JSON string '{"a":{"b":"hello"}}':
- Extract(jsonStr, "a.b") returns "hello"
- Replace(jsonStr, "world", "a.b") returns '{"a":{"b":"world"}}'
The config string is not used (pass "" when creating).
func (*JSONAccessor) ExistsP ¶ added in v0.1.14
func (ja *JSONAccessor) ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
func (*JSONAccessor) Extract ¶ added in v0.1.14
func (ja *JSONAccessor) Extract(currentFieldValue, path string) (any, error)
type LineAccessor ¶ added in v0.1.14
type LineAccessor struct{}
LineAccessor is an EmbeddedAccessor that accesses individual lines of a multi-line string value by line number. The path is a 1-based line number (as a string).
For example, given a multi-line string "line one\nline two\nline three\n":
- ExistsP(doc, "2") returns true
- Data(doc, "2") returns "line two"
- SetP(doc, "new line two", "2") replaces line 2
- Extract("line one\nline two\n", "1") returns "line one"
The config string is not used (pass "" when creating).
func (*LineAccessor) ExistsP ¶ added in v0.1.14
func (la *LineAccessor) ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
func (*LineAccessor) Extract ¶ added in v0.1.14
func (la *LineAccessor) Extract(currentFieldValue, path string) (any, error)
type LintConfig ¶ added in v0.1.25
type LintConfig struct {
NoAnchors bool // Ban anchors (&anchor) and aliases (*alias)
NoEmptyValues bool // Ban implicit null values (key: with no value)
NoDuplicateKeys bool // Ban duplicate keys in mappings
NoTruthy bool // Ban unquoted yes/no/on/off/y/n (YAML 1.1 booleans)
NoOctalValues bool // Ban old-style octal integers (0755, 010)
}
LintConfig controls which lint rules are enabled.
func DefaultLintConfig ¶ added in v0.1.25
func DefaultLintConfig() LintConfig
DefaultLintConfig returns a LintConfig with all rules enabled.
type LintFinding ¶ added in v0.1.25
type LintFinding struct {
Rule string // Rule identifier, e.g., "no-anchors", "no-truthy"
Message string // Human-readable description of the violation
Path string // Dot-notation path to the offending node, e.g., "spec.containers.0.image"
Line int // 1-based line number from the source YAML
Column int // 1-based column number from the source YAML
}
LintFinding represents a single lint rule violation found in a YAML document.
func LintBytes ¶ added in v0.1.25
func LintBytes(data []byte) ([]LintFinding, error)
LintBytes parses raw YAML bytes into a yaml.Node tree and lints it. This is a convenience function for standalone use outside of gaby. It handles a single YAML document; for multi-document YAML, use LintNode with each document's node separately.
func LintNode ¶ added in v0.1.25
func LintNode(node *yaml.Node, config LintConfig) []LintFinding
LintNode walks a yaml.Node tree and returns all lint findings. The node may be a DocumentNode (from yaml.Unmarshal) or a MappingNode/SequenceNode (from kyaml's Parse or gaby's YNode).
type MergeKeyEntry ¶ added in v0.1.15
type MergeKeyEntry struct {
Key string // merge key field name (e.g., "name")
Value string // merge key value (e.g., "config")
}
MergeKeyEntry represents a merge key/value pair extracted from an associative path segment.
func ExtractMergeKeysFromPath ¶ added in v0.1.15
func ExtractMergeKeysFromPath(path string) []MergeKeyEntry
ExtractMergeKeysFromPath extracts merge key/value pairs from associative path segments. Path segments of the form ?key=value;@index yield {Key: key, Value: value}.
type MergeKeyField ¶ added in v0.4.8
type MergeKeyField struct {
Path string `json:"path"`
Key string `json:"key"`
ExtraKeys []string `json:"extraKeys,omitempty"`
}
MergeKeyField describes a strategic merge patch key for an array field. Path is the dot-separated path to the array field (gaby dot syntax), relative to whatever root the declaration sits at. Wildcards (*) represent any array index within the path. Key is the field name within array items used as the merge key.
ExtraKeys names the remaining fields of a composite key, for the arrays Kubernetes declares with more than one x-kubernetes-list-map-key: a container port is identified by its number and its protocol, and a topology spread constraint by its topology key and its whenUnsatisfiable. Two elements that agree on Key alone but differ in an ExtraKey are different elements, and matching them would merge one into the other.
func (MergeKeyField) Keys ¶ added in v0.4.8
func (f MergeKeyField) Keys() []string
Keys returns the full key list, Key first.
type MergeKeyLookup ¶
MergeKeyLookup is a function that returns the merge key field names for a given array path, if any exist. It is used by ComputeMutationsForDocs to match array elements by merge key value instead of positional index.
type PathEnricher ¶ added in v0.4.8
type PathEnricher func(api.ResourceType, api.PathToVisitorInfoType)
PathEnricher adds per-path detail that only a toolchain can compute -- a field description read out of its schema, say -- to the paths about to be registered for one resource type.
type RegexpAccessor ¶
RegexpAccessor is an EmbeddedAccessor that uses regular expressions to extract and insert subparts of a structured string value.
func (*RegexpAccessor) ExistsP ¶
func (ra *RegexpAccessor) ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
func (*RegexpAccessor) Extract ¶
func (ra *RegexpAccessor) Extract(currentFieldValue, path string) (any, error)
type RegexpMatcher ¶ added in v0.1.76
RegexpMatcher matches string values for which Regexp finds a match, providing sed-like regular expression matching.
func (RegexpMatcher) Matches ¶ added in v0.1.76
func (m RegexpMatcher) Matches(value any) bool
type ResolvedPathInfo ¶
type ResolvedPathInfo struct {
Path api.ResolvedPath
PathArguments []api.FunctionArgument
}
ResolvedPathInfo contains a fully resolved path and any named path parameters specified in the unresolved path expression (using ?, *?, or *@).
func ResolveAssociativePaths ¶
func ResolveAssociativePaths( doc *gaby.YamlDoc, unresolvedPath api.UnresolvedPath, resolvedPath api.ResolvedPath, upsert bool, accessor EmbeddedAccessor, ) ([]ResolvedPathInfo, error)
ResolveAssociativePaths resolves an associative path with associative lookups (?) and wildcards (*, *?, *@) into specific resolved paths and discovered path parameters. See the documentation for api.UnresolvedPath for more details. If accessor is non-nil, it is used as a fallback for associative lookups on scalar array elements where the element has no map fields (e.g., pflags like "--key=value").
type ResourceCategoryTypeToNamesMap ¶
type ResourceCategoryTypeToNamesMap map[api.ResourceCategoryType][]api.ResourceName
type ResourceInfoToDocMap ¶
type ResourceInfoToDocMap map[api.ResourceInfo]int
func ResourceToDocMap ¶
func ResourceToDocMap(parsedData gaby.Container, resourceProvider ResourceProvider) (resourceMap ResourceInfoToDocMap, err error)
ResourceToDocMap returns a map of all resources in the provided list of parsed YAML documents to their document index.
type ResourceNameToCategoryTypesMap ¶
type ResourceNameToCategoryTypesMap map[api.ResourceName][]api.ResourceCategoryType
type ResourceProvider ¶
type ResourceProvider interface {
DefaultResourceCategory() api.ResourceCategory
ResourceCategoryGetter(doc *gaby.YamlDoc) (api.ResourceCategory, error)
ResourceTypeGetter(doc *gaby.YamlDoc) (api.ResourceType, error)
ResourceNameGetter(doc *gaby.YamlDoc) (api.ResourceName, error)
// ResourceNameStableCoreGetter returns the stable core of the resource name, with
// generated prefixes and suffixes stripped. Returns empty string if not present.
ResourceNameStableCoreGetter(doc *gaby.YamlDoc) (api.ResourceName, error)
RemoveScopeFromResourceName(resourceName api.ResourceName) api.ResourceName
ScopelessResourceNamePath() api.ResolvedPath
SetResourceName(doc *gaby.YamlDoc, name string) error
ResourceTypesAreSimilar(resourceTypeA, resourceTypeB api.ResourceType) bool
TypeDescription() string
NormalizeName(name string) string
NameSeparator() string
ContextPath(contextField string) string
GetPathRegistry() api.AttributeNameToResourceTypeToPathToVisitorInfoType
GetAttributeRegistry() api.AttributeNameToAttributeDescriptor
GetRegistry() *ResourceProviderRegistry
// MergeKeysForPath returns the merge key field names for the given resource type
// and array path, if any exist. The path should use dot-separated segments
// where array indices may be numeric or wildcards. The implementation normalizes
// numeric indices to wildcards for lookup. Returns (nil, false) if no merge key
// is defined for the path.
//
// More than one key is returned for an array whose elements are identified by a
// tuple rather than a single field: a Kubernetes container port is identified by
// its number *and* its protocol, and a topology spread constraint by its topology
// key *and* its whenUnsatisfiable. Matching such an element on the first field
// alone pairs elements that are not the same element.
MergeKeysForPath(resourceType api.ResourceType, path string) ([]string, bool)
// ExclusiveFieldsForPath returns the mutually exclusive sibling fields of the object
// at the given path, if the schema declares any. Kubernetes handles the class with
// patchStrategy:"retainKeys": setting one member of a union has to clear the others,
// or the result is a resource the API server rejects — a volume with two sources, a
// Recreate strategy that still carries rollingUpdate. Returns ok=false when the path
// holds no union, which is the ordinary case.
ExclusiveFieldsForPath(resourceType api.ResourceType, path string) (ExclusiveFields, bool)
// IsMapKeyPath returns true if the given path is a freeform map (e.g., labels,
// annotations) whose children are dynamic keys rather than schema fields.
// During path normalization, child segments of map paths are converted to wildcards.
IsMapKeyPath(resourceType api.ResourceType, path string) bool
GetToolchainType() workerapi.ToolchainType
}
The ResourceProvider interface is used to perform toolchain-specific operations.
type ResourceProviderRegistry ¶ added in v0.1.15
type ResourceProviderRegistry struct {
PathRegistry api.AttributeNameToResourceTypeToPathToVisitorInfoType
AttributeRegistry api.AttributeNameToAttributeDescriptor
// contains filtered or unexported fields
}
ResourceProviderRegistry holds what one provider knows: the path and attribute registries its functions read, and the compiled structure its lookups answer from. Every ResourceProvider embeds it, so all of that is per-instance and built during construction -- which is what §5.2 of docs/design/resource-type-specs.md asks for, and why the structure lookups below are not package globals.
func NewResourceProviderRegistry ¶ added in v0.1.15
func NewResourceProviderRegistry(toolchainType workerapi.ToolchainType) ResourceProviderRegistry
NewResourceProviderRegistry creates a registry for a toolchain that declares no structure.
func NewResourceProviderRegistryWithSpecs ¶ added in v0.4.10
func NewResourceProviderRegistryWithSpecs(toolchainType workerapi.ToolchainType, specs *CompiledSpecs) ResourceProviderRegistry
NewResourceProviderRegistryWithSpecs creates a registry whose structure lookups read the given compiled specs.
func (*ResourceProviderRegistry) ExclusiveFieldsForPath ¶ added in v0.4.10
func (r *ResourceProviderRegistry) ExclusiveFieldsForPath(resourceType api.ResourceType, path string) (ExclusiveFields, bool)
ExclusiveFieldsForPath implements the ResourceProvider method for every toolchain. The path may use numeric indices or associative segments; both normalize to wildcards for lookup, as they do for merge keys.
func (*ResourceProviderRegistry) GetAttributeRegistry ¶ added in v0.1.15
func (r *ResourceProviderRegistry) GetAttributeRegistry() api.AttributeNameToAttributeDescriptor
func (*ResourceProviderRegistry) GetPathRegistry ¶ added in v0.1.15
func (r *ResourceProviderRegistry) GetPathRegistry() api.AttributeNameToResourceTypeToPathToVisitorInfoType
func (*ResourceProviderRegistry) GetRegistry ¶ added in v0.1.15
func (r *ResourceProviderRegistry) GetRegistry() *ResourceProviderRegistry
func (*ResourceProviderRegistry) IsMapKeyPath ¶ added in v0.4.10
func (r *ResourceProviderRegistry) IsMapKeyPath(resourceType api.ResourceType, path string) bool
IsMapKeyPath implements the ResourceProvider method for every toolchain. The path should end with ".*", since the question is always about a path's children.
func (*ResourceProviderRegistry) MergeKeysForPath ¶ added in v0.4.10
func (r *ResourceProviderRegistry) MergeKeysForPath(resourceType api.ResourceType, path string) ([]string, bool)
MergeKeysForPath implements the ResourceProvider method for every toolchain. See the interface for what it answers and why more than one key comes back.
type ResourceTypeSpec ¶ added in v0.4.8
type ResourceTypeSpec struct {
Type api.ResourceType `json:"type"`
ToolchainType workerapi.ToolchainType `json:"toolchainType,omitempty"`
Declaration
// Scope is what this type's names are scoped by, in the toolchain's own terms.
Scope Scope `json:"scope,omitempty"`
// SimilarityClass names a set of types that are interchangeable enough that a mutation to
// one can be replayed against another -- Kubernetes workload controllers, which carry a pod
// spec in the same place, are the case it exists for. Two types are similar when they
// declare the same class. It is a free string so that a toolchain names its own classes.
SimilarityClass string `json:"similarityClass,omitempty"`
// ApplyPriority orders this type against others when a set of resources is applied
// together; lower goes first. A pointer, because zero is a usable priority and "unset" has
// to be distinguishable from it.
ApplyPriority *int `json:"applyPriority,omitempty"`
// Schema is where this type's schema is, for a type the set's SchemaLocations do not
// address. Two values are special: empty means "try the set's locations", and "none"
// means this type has no schema to find. The difference matters to a validator, which
// otherwise cannot tell a type it skipped from a type that passed -- the distinction
// vet-schemas passes silently over today.
Schema string `json:"schema,omitempty"`
}
ResourceTypeSpec is what any toolchain declares about one resource type. ToolchainType may be left empty, in which case the containing SpecSet's applies.
The three fields below the declaration are carried rather than interpreted: the compiler stores them and hands them back, and what they mean is the toolchain's business. They are here rather than on a per-toolchain type because the concepts generalize -- ResourceTypesAreSimilar and the scope of a resource name are already on the ResourceProvider interface -- and because one spec file, one loader and one stored representation is what §6.1 and §9.3 need. A spec registering a CRD has to be able to say the CRD's scope, and it is written in the same file as everything else.
type ResourceTypeToPathPrefixSetType ¶
type ResourceTypeToPathPrefixSetType map[api.ResourceType]map[string]struct{}
type ResourceVisitorFunc ¶
type ResourceVisitorFunc func(doc *gaby.YamlDoc, output any, index int, resourceInfo *api.ResourceInfo) (any, []error)
ResourceVisitorFunc defines the signature of functions invoked by the resource visitor function.
type Scope ¶ added in v0.4.10
type Scope string
Scope says what a resource type's names are scoped by. Every toolchain already has the concept -- ResourceProvider carries RemoveScopeFromResourceName and ScopelessResourceNamePath -- but not the same values, so the values are the toolchain's to define. Kubernetes has two, below; another toolchain may have others, or more than two.
type ShapeEmbed ¶ added in v0.4.8
ShapeEmbed places a shape at a path within a type or another shape. Shape is the shape's name in the set's Shapes; Path is relative to the embedding declaration's root, and may be empty to embed at that root.
type SpecSet ¶ added in v0.4.8
type SpecSet struct {
ToolchainType workerapi.ToolchainType `json:"toolchainType,omitempty"`
Shapes map[string]Declaration `json:"shapes,omitempty"`
ResourceTypes []ResourceTypeSpec `json:"resourceTypes,omitempty"`
// SchemaLocations are where a type's schema is fetched from, most authoritative first.
// Each is a template over the resource type, in the syntax kubeconform reads, so one
// entry covers every type rather than each type naming its own URL -- which would be the
// per-type table this file exists to remove.
//
// They are per set rather than per type because that is the granularity at which they
// vary: a catalog covers a whole family of types, and adding a catalog is one line.
// ResourceTypeSpec.Schema is for the type whose schema is not where the templates say.
SchemaLocations []string `json:"schemaLocations,omitempty"`
}
SpecSet is a set of resource-type specs and the shapes they embed: one file, and the unit a stored spec Unit would hold. ToolchainType is the default for specs that do not state one, so a single-toolchain file states it once.
func LoadSpecSet ¶ added in v0.4.8
LoadSpecSet parses a spec set from YAML or JSON.
type StringContainsMatcher ¶ added in v0.1.76
type StringContainsMatcher struct {
Substring string
}
StringContainsMatcher matches string values that contain Substring.
func (StringContainsMatcher) Matches ¶ added in v0.1.76
func (m StringContainsMatcher) Matches(value any) bool
type ValueMatcher ¶ added in v0.1.76
type ValueMatcher interface {
// Matches reports whether the given scalar value (string, int, float64,
// bool, etc.) matches.
Matches(value any) bool
}
ValueMatcher decides whether a scalar value found while traversing a YAML structure should be collected by FindYAMLPathsByValue.
type VisitorContext ¶
type VisitorContext struct {
api.AttributeInfo // includes Path and Info
Arguments []api.FunctionArgument
EmbeddedPath string
Accessor EmbeddedAccessor
PathVisitorInfo *api.PathVisitorInfo
}
VisitorContext contains information passed to visitor functions for each path traversed.
type VisitorFunc ¶
type VisitorFunc[T api.Scalar] func(doc *gaby.YamlDoc, output any, context VisitorContext, currentValue T) (any, error)
VisitorFunc defines the signature of functions invoked by the visitor functions.
type VisitorFuncAnyType ¶
type VisitorFuncAnyType func(doc *gaby.YamlDoc, output any, context VisitorContext, currentValue any) (any, error)
VisitorFuncAnyType defines the signature of functions invoked by the visitor functions.
type VisitorFuncDoc ¶
type VisitorFuncDoc func(doc *gaby.YamlDoc, output any, context VisitorContext, currentDoc *gaby.YamlDoc) (any, error)
VisitorFuncDoc defines the signature of functions invoked by the visitor function.
type YAMLAccessor ¶ added in v0.1.14
type YAMLAccessor struct{}
YAMLAccessor is an EmbeddedAccessor that accesses fields within a YAML string value embedded in a YAML scalar. The path uses dot-separated segments to navigate the parsed YAML structure.
For example, given a YAML field containing the string "a:\n b: hello\n":
- Extract(yamlStr, "a.b") returns "hello"
- Replace(yamlStr, "world", "a.b") returns "a:\n b: world\n"
The config string is not used (pass "" when creating).
func (*YAMLAccessor) ExistsP ¶ added in v0.1.14
func (ya *YAMLAccessor) ExistsP(scalarYamlDoc *gaby.YamlDoc, path string) bool
func (*YAMLAccessor) Extract ¶ added in v0.1.14
func (ya *YAMLAccessor) Extract(currentFieldValue, path string) (any, error)