-
-
Notifications
You must be signed in to change notification settings - Fork 23
yaml merge Anchor Options
The yaml-merge
command-line tool enables users to control how it handle conflicting Anchors during a merge operation. Non-conflicting Anchors are automatically merged and the definition-use order between each Anchor and its Aliases is preserved during the merge. An Anchor conflict occurs only when the same Anchor name is used in both of the LHS and RHS documents and the Anchored value is different between them.
Any attempt to merge with Anchor conflicts when using default options will result in an error. This is because the yaml-path
tool will refuse any operation which would destroy data unless the user explicitly instructs it to do so, and how. Not all Anchor conflict resolution options are destructive; the rename
option reserves all Anchors and their Aliases in both documents by uniquely renaming conflicting Anchors and Aliases in the RHS document.
But what are Anchors? In short:
Anchors are a name assigned to a Scalar or Hash YAML data element. This name is prefixed with an
&
sign. Beyond that point within the YAML data, the data which was "anchored" can be re-used any number of times by referencing the Anchor via its Alias form whereby the&
is replaced with an*
sign.
In other words, YAML defines two kinds of Anchors. Scalar Anchors define reusable Scalar values (which are String, Integer, Float, Boolean, etc. data types). Hash Anchors (AKA Map Anchors or Dictionary Anchors). To date, there is no definition in YAML for an Array Anchor (AKA List Anchor AKA Sequence Anchor).
Each of these Anchor types will be explored in how they are merged based on user option selection. When there is no conflict, RHS Anchors are merged into the LHS document no matter what Anchor merge option is selected. In order to resolve Anchor conflicts, the yaml-merge
tool's available Anchor merge options include:
-
stop
(the default) causes merging to abort upon detection of an Anchor conflict. -
left
causes LHS Anchors to overwrite conflicting RHS Anchors. -
right
causes RHS Anchors to overwrite conflicting LHS Anchors. -
rename
causes RHS Anchors to be automatically and uniquely renamed before they are merged into the LHS document. The RHS document is updated to use the new Anchor name everywhere its Aliases appear before the merge.
Scalar Anchors are usually gathered up into a special Array named aliases:
near the top of each YAML file. Such a file might look like:
File: LHS1.yaml
---
aliases:
- &scalar_anchor_string This is a reusable String value
- &scalar_anchor_integer 5280
a_hash:
which_reuses:
those_anchors:
string_alias: *scalar_anchor_string
integer_alias: *scalar_anchor_integer
in_several_places:
string_alias: *scalar_anchor_string
integer_alias: *scalar_anchor_integer
Were you to query the YAML file at /a_hash/which_reuses/those_anchors/string_alias
(or a_hash.which_reuses.those_anchors.string_alias
), you'd get back This is a reusable String value
.
We can impose an Anchor conflict by attempting to merge with:
File: RHS1.yaml
---
aliases:
- &scalar_anchor_string A DIFFERENT STRING VALUE
- &scalar_anchor_integer 5280
another_hash:
another_alias_string: *scalar_anchor_string
another_alias_integer: *scalar_anchor_integer
Notice that RHS1.yaml redefines &scalar_anchor_string
but not &scalar_anchor_integer
. In this case, only &scalar_anchor_string
is in conflict. A query against /another_hash/another_alias_string
(or another_hash.another_alias_string
) in RHS1.yaml would yield A DIFFERENT STRING VALUE
.
The next sub-sections are examples of the various ways to deal with such an Anchor conflict.
You can instruct yaml-merge
to override the value of conflicting Anchors in the RHS document. By setting --anchors=left
or -a left
, yaml-merge
would produce this output:
---
aliases:
- &scalar_anchor_string This is a reusable String value
- &scalar_anchor_integer 5280
- *scalar_anchor_string
- *scalar_anchor_integer
a_hash:
which_reuses:
those_anchors:
string_alias: *scalar_anchor_string
integer_alias: *scalar_anchor_integer
in_several_places:
string_alias: *scalar_anchor_string
integer_alias: *scalar_anchor_integer
another_hash:
another_alias_string: *scalar_anchor_string
another_alias_integer: *scalar_anchor_integer
Notice that the RHS Anchors were turned into Aliases of the same-named LHS Anchors. Because the default option for Arrays is to preserve all
elements from both documents during the merge, the aliases:
array receives the redefined Anchors-as-Aliases from the RHS document. This is normal and you can override this behavior.
If you were to repeat the previous two queries against the merged document, you'd get:
-
/a_hash/which_reuses/those_anchors/string_alias
= This is a reusable String value -
/another_hash/another_alias_string
= This is a reusable String value