In YAML how to use value from another key - yaml

I have a YAML file like below.
Details:
Name: Jack
Location: USA
ABC: TestValue
Refer:
Test1: %Details.Name%
Test2: %Details.Location%
Wanted to check if the value given in Test1 works? As I know if %Details.Name% is present under parameters. But above keys are not parameters. So, is there any way to refer the values from another key?

There are anchors and aliases, which you can use like this:
Details:
Name: &name Jack
Location: &location USA
ABC: TestValue
Refer:
Test1: *name
Test2: *location
However, there is no way to refer to other values via their „paths“. Applications using YAML may support pre- or postprocessing to do this (often via templating engines like Jinja), but plain YAML doesn't implement this feature.
If you are under the impression that %Details.Name% would work in some context, you are already using a pre- or postprocessing feature that is not plain YAML.

Related

Helm split global section

I have a helm values.yaml file like below
global:
foo: bar
foo1: bar1
random-chart:
fooo: baar
My use case is to append values in both global and random-chart during run time.
After appending values, the chart looks like this.
global:
foo: bar
foo1: bar1
random-chart:
fooo: baar
global:
secret: password
random-chart:
secret1: password1
Since there's 2 different global and random-chart keys. Will it work as intended and is it a good practice to do that?
This probably won't work as intended.
The YAML 1.2.2 spec notes (emphasis from original):
The content of a mapping node is an unordered set of key/value node pairs, with the restriction that each of the keys is unique.
And in discussing loading errors continues:
... mapping keys may not be unique ....
So the YAML file you show has a mapping with two keys both named global and two keys both named random-chart, and that's not valid. Depending on the specific YAML library that's being used, this might be interpreted as a loading error, or the library might just pick the last value of global.
In general, it's hard to work with YAML files using line-oriented shell tools, since there are so many syntactic variations. A dedicated library in a higher-level language will usually work better. For example, using the Python PyYAML library:
import yaml
with open('values.in.yaml', 'r') as f:
values = yaml.safe_load(f)
values['global']['secret'] = 'password'
values['random-chart']['secret-1'] = 'password1'
with open('values.out.yaml', 'w') as f:
yaml.dump(values. f)
Two other possibilities to consider: you can have multiple helm install -f options, so it's possible to write out a file with just the values you're adding, and those will be merged with other settings (you do not need to repeat the values from the chart's values.yaml file). Depending on your environment, you also may find it easier to dynamically write out JSON files, particularly if you don't need to re-read the base chart; setups like Jenkins or Javascript applications will have built-in JSON support, and valid JSON turns out to be valid YAML.

Extract from YAML values dynamically

Consider the following yaml file:
topics:
topicA:
bins:
type: multi-bins
map:
FirstBin:
source: value-field
field-name: ServiceID
SecondBin:
source: value-field
field-name: ServiceID
message-transformer:
class: com.aerospike.connect.inbound.transforms.TombstoneMessageTransformer
params:
shouldDeleteOnNull: "FirstBin, SecondBin"
topicB:
...
As you can see there duplication between the topics.<topic-name>.bins.map.keys and topics.<topic-name>.message-transformer.params.shouldDeletedOnNull
Is there a way to extract the values dynamically? I want to send to shouldDeleteOnNull all the keys of topics.<topic-name>.bins.map
Note: I don't want to create an env variable for that and use Yaml anchors.
YAML is not a programming language. It doesn't let you extract anything and it doesn't let you send anything, because it does not provide you with any kind of actions or processing instructions.
While you can reference nodes multiple times with anchors, that doesn't help you here because you would need to concatenate values, which is not something that is possible in YAML. A solution that would work looks like this (shortened for clarity):
map:
&a FirstBin:
source: value-field
field-name: ServiceID
&b SecondBin:
source: value-field
field-name: ServiceID
shouldDeleteOnNull: [*a, *b]
As you can see, I needed to make shouldDeleteOnNull a sequence rather than a scalar to make this work. This does not seem like much of an improvement.
Anything more sophisticated would need to be implemented in the code loading the file and therefore does not make sense to be discussed in a pure YAML context.

How to use a value from another property in the same yaml file?

I have property file application-dev.yml with content:
spring.profiles: dev
config:
value: test
property: test2
foo:
value: test
property: test2
bar:
value: test
property: test2
There are some redundant values to my properties and in case I ever want to change test to blah and test2 to blah2, I would have to go to every instance of the text and change it.
Is there some way I can (in Java terms) declare a variable and assign it to `test' and just use the variable throughout my yaml file so that I consolidate the text and make it easier to change in the future if needed?
YAML does have anchors and aliases, which allow you to identify a certain value by giving it an anchor, and later reference it again with an alias:
spring.profiles: dev
config:
value: &a test
property: &b test2
foo:
value: *a
property: *b
bar:
value: *a
property: *b
Mind that this is not the same as a variable. YAML serializes a node graph, which is in its most common form, i.e. without using anchors/aliases, a tree structure. You can use anchors & aliases to serialize any directed graph structure, including cyclic graphs. This is what the feature is for.
The difference to a variable is that you do not have a definition of the value – instead, you add the anchor to the first occurrence of the value. You can then reference it in subsequent occurrences. Other differences include that you cannot process the value in any way, e.g. via string concatenation or interpolation. For example, if you want some key to have the value testtest2, you cannot express that via the aliases *a and *b.

How can I reference a YAML anchor from another YAML anchor?

I have a YAML file which has several different keys that I want to provide the same value for. Additionally, I want this value to be easily configurable.
See YAML for my specific use-case below:
---
# Options for attribute_value
att_value_1: &att_value_1
att_value_2: &att_value_2
# There could be more options...
# This is where the constant is being set.
attribute_value: &attribute_value *att_value1
items:
- name: item1
attributes:
attribute_for_item1: *attribute_value
- name: item2
attributes:
attribute_for_item2: *attribute_value
Here is a simplified YAML which demonstrates the problem:
---
foo: &foo "Hello World!"
bar: &bar *foo
Error (it's complaining about the first line that has "Hello World!" on it):
(<unknown>): did not find expected key while parsing a block mapping at line 2 column 1
I expect the value to propagate.
Error (it's complaining about the first line that has "Hello World!" on it):
You have to tell us which YAML implementation you're using. PyYAML and NimYAML both correctly report that the error is in the third line; the second line is okay.
I expect the value to propagate.
There is nothing in the specification that backs this expectation. The spec says:
Note that an alias node must not specify any properties or content, as these were already specified at the first occurrence of the node.
Properties are anchors and tags. You cannot put an anchor on an alias node since it already has an anchor.
In your example,
---
foo: &foo "Hello World!"
bar: &bar *foo
&bar is completely superfluous since you already can refer to the "Hello World" node via *foo and therefore, there is no point in introducing &bar.
To answer your question: You cannot reference a YAML anchor from another YAML anchor, because a YAML anchor is not a node. YAML represents a graph, i.e. nodes and directed edges. Anchors and aliases are used to reference the same node multiple times (not to copy values as you might think). This also means that everything within a YAML file is content. There is no such thing as variable declarations.
It seems you are using the wrong tool for your use-case. To configure YAML files with external values, you would typically use a templating engine (SaltStack and Ansible use Jinja for example) and generate your YAML file from a template. You could supply your options in another YAML file. This would clearly separate the configuration options from the content.

Ansible YAML attribute reading [duplicate]

I am trying to make sense of a variable reference I found in an incomplete Ansible role. The role references a value using
dest: “{{params['box'].t1}}”
In a separate yaml file I have
box:
t1: "Albany"
t2: "Albuquerque"
params isn't defined, so obviously this isn't going to work, but I can't figure out the correct way to define it. Can someone tell me where (or how) params must be defined for this variable reference to work in Ansible?
Related questions. Does the use of square brackets in dest: “{{params['box'].t1}}” indicate that it is a dictionary? If yes, could I also write this as dest: “{{params['box']['t1']}” or dest: “{{params.box.t1}”?
params['box'].t1 refers to Albany in:
params:
box:
t1: "Albany"
t2: "Albuquerque"
It is the same as params.box.t1 and params['box']['t1'].
Brackets refer to a key name, so they imply it is a dictionary.
You typically use square bracket-notation when you want to refer to a key via a variable:
vars:
wanted_key: box
params:
box:
t1: Albany
other:
t1: Albuquerque
Then params[wanted_key].t1 refers to Albany.
In your example the value inside square brackets is a string (quoted), so all above examples are equivalent.

Resources