YAML is a sequential data language designed to be easy to read. It has four main syntactic features.
Keywords in yaml are represented as a word followed by a colon on a line by itself.
accessConfigs:
Key value pairs are represented with the key and value on either side of a colon on a line by itself.
key: value
Nesting of elements occurs through indentation (like Python) rather than braces or brackets as in other languages, but the number of spaces is not significant.
accessConfigs:
name: samuel
type: clemens
Is the same as
accessConfigs:
name: samuel
type: clemens
Never use tabs in YAML.
Finally, a list is represented by a dash in the whitespace before the start of the list and is terminated by the end of the in-line indentation.
accessConfigs:
name: samuel
type: clemens
This one produces a sequence: accessConfigs( name:samuel, type:clemens )
Notice that each pair is a property.
that is different from
accessConfigs:
- name: samuel
type: clemens
This one produce a list: accessConfigs( [ (name:samuel), (type:clemens) ], … )
Notice that the collection of pairs is the first property.
This means that when you create a YAML file, if you get a dash out of place or leave it off when it is expected, it will create a syntax error in the call to the underlying API and your deployment will fail.
Syntax complications
The YAML language you write is used ultimately by Deployment Manager to make API calls. There are syntax complications due to the underlying API. You need to understand these complications to correctly write YAML. Simplified pseudo-code will help explain the syntax requirements.
Imagine that in the API, to create a virtual machine instance you needed to call the function ‘make_a_computer( )’. This is a pseudo-code illustration. This is NOT the real function that is in the Cloud API and this is NOT valid YAML. This is just an illustration to help you understand the required syntax.
In our pseudocode language, to create a virtual machine, you would call
make_a_computer( properties )
However a virtual machine requires a boot disk, but the boot disk is not actually a component of the instance. It is a separate object. You could create a disk without a virtual machine like this:
make_a_disk( properties )
So, since a virtual machine requires a boot disk, and the disk is a separate object, you must use a nested construction to create the virtual machine:
make_a_computer( properties, make_a_disk( disk_properties ), )
1) The API and therefore the YAML requires this kind of nested construction.
You cannot create a virtual machine without a disk. Each computer requires at least one disk. So if you were just to use the following construction to create a virtual machine, without the disk specification, it would result in an error:
make_a_computer ( properties ) <<== ERROR
2) Leaving out a required nested element generates an error.
The next syntax complication concerns the properties. There are a few ways that properties can be identified. Imagine that one required property is the virtual machine’s ‘name’. One way to specify a property is by position.
In this example, the first property is always the virtual machine’s name:
make_a_computer( my_name, make_a_disk( disk_properties ), more_properties )
If you leave the name out, a default name for the computer is used. All you would do is leave the comma in the properties sequence, but don’t put a name in that position, and the system knows that you have not given the computer a name and that it should use the default name.
make_a_computer( , make_a_disk( disk_properties ), more_properties )
Instead of positional properties, another way to specify properties is a tuple. A tuple is nothing more than a key-value pair. The keyword comes first, then the colon symbol, followed by the value. key:value. So here is how you would specify a name property using a tuple.
make_a_computer( name:my_name, make_a_disk( disk_properties ), more_properties )
One advantage of using a tuple instead of a positional property is that a tuple can appear anywhere in the properties list. It is no longer locked into the first position. So the following example is now a valid way of specifying the computer name. Notice the tuple is now in third position.
make_a_computer( properties, make_a_disk( disk_properties ), name:my_name, more_properties )
If you wanted to use the default name, how would you represent that with tuples? You can’t leave the comma as in the previous default name example, because position is no longer significant in the list of properties. The answer is, you simply leave out the property. When the system reaches the end of the properties sequence and has found no tuple for “name:?”, it knows to take the default (if there is one). For properties that have no default, the system generates an error.
This example triggers the use of the default name by simply not specifying a name tuple.
make_a_computer( make_a_disk( disk_properties ), )
3) The API and YAML use tuple construction for properties.
4) You specify defaults, when they exist, by simply omitting the tuple from the list of properties.
There is one final syntax complication. Imagine the disk has the following disk_properties:
disk_type: { magnetic or solid_state } (required, there is no default)
disk_size: { N megabytes; where N is greater than or equal to 10, no default }
disk_SKU: { optional suppliers part number } (may appear multiple times)
The disk_SKU is the part number to order a replacement disk. There could be as many of these properties as there are disk manufacturers. One supplier would have disk_SKU:xyz and another disk_SKU:123. It can appear in the properties sequence multiple times.
How can the API developer know how many properties to ingest from the function? The number of properties is no longer fixed.
To get around this problem, the developer might require a single property — a list object. That list can contain an arbitrary number of tuples.
Instead of this:
make_a_disk( disk_properties )
The API might require this:
make_a_disk( [ list ] )
In some languages a list is shown within square brackets:
Without a list; a property sequence.
make_a_disk( disk_size:10, disk_type:magnetic )
With a list.
make_a_disk( [disk_size:10, disk_type:magnetic] )
Note that even though the list format was adopted to allow for multiple disk_SKU properties, that because the property is also optional, in the above example it does not appear in the list.
If the API developer has required a list instead of a property sequence, then calling the API with the individual properties rather than with the list construct is a syntax error:
make_a_disk( disk_size:10, disk_type:magnetic ) <<== ERROR
5) The API uses both property sequences and lists. If a list is required and you specify a property instead of a list, it is a syntax error.
Links: