Difference between revisions of "YAML Syntax"

From Ever changing code
Jump to navigation Jump to search
 
(25 intermediate revisions by the same user not shown)
Line 35: Line 35:
* Encoding: UTF-8, 16, 32
* Encoding: UTF-8, 16, 32
* To be JSON compatibile must be UTF-32
* To be JSON compatibile must be UTF-32
= Mappings =
Mappings are also known as:
* assosiative arrays
* hash tables
* kv pairs
* collection (YAML specific term, that groups things indented at the same level)
{| class="wikitable"
|+ Mappings, the colon-space combination that marks it as a mapping
|-
! Block style
! Flow style
|- style="vertical-align:top;"
| <source lang=yaml>
host: host-1
datacenter:
  location: Poland
  cabinet: 11
# cabinet: 12  #the same keys are not allowed
</source>
| <source lang=yaml> host: host-1
datacentre: { location: Poland, cabinet: 11 } </source>
|}
= Sequences (list) =
Also known as:
* Lists, dictionary, arrays or collections
* Denoted with a dash <tt>-</tt> and space
* Can be combined with mappings:
** mapping of sequences
** sequence of mapping
** list of maps
Sequence
<source lang=yaml>
host: host-1    # sequence/list of mappings
  - datacenter:
    location: Poland
    cabinet: 11
roles:          # sequence
  - web
  - dns
  - ""  #blank lines are not allowed, thus double-quotes are required
</source>
Flow style sequence
<source lang=yaml>
roles: [ web, dns, "" ]
</source>
= Examples of lists and maps =
Sequences are lists
<source lang=yaml>
- Item 1
- Item 2
</source>
Mappings are key-value pairs
<source lang=yaml>
key1: value1
key2: value2
</source>
A sequence of mappings:
<source lang=yaml>
- key1: value1
  key2: value2
</source>
A mapping of mappings:
<source lang=yaml>
overallkey:
  key1: value1
  key2: value2
</source>
= Scalars =
Scalar is a string, number of boolean with whitespace permitted.
<source lang=yaml>
---
host: host-1   
datacenter:
  location: "Poland\n" # double-quotes allow escape sequences, "\n" - will be read as new-line
  cabinet: '11'        # change a number into string single or double-quotes
roles:         
  - web
  - dns
  - ""  #blank lines are not allowed, thus double-quotes are required
comments: | # pipe (multiline scalar) it preserves newlines
  Comment 1 note of the required indent
  Comment 2
comments_other: > # right chevron (folded scalar) does not preserve new lines, but helps with code readibility
                  # converts newlines /spacing into single space.
  Other_comment is that indent is still needed
  Another comment.
<tab><tab> item-1 this preserves new lines to create a list
<tab><tab> item-2
</source>
= [https://yaml-multiline.info/ Block Scalars] - control multiline string =
Check ^^ link above.
= Structures =
YAML allows for multiple directive/documents in one file. The document/directive starts with <code>---</code> but it's often optional for single directive files. Ansible requires it but not Salt. The delimiters are reuired for multi-directive files.
<source lang=bash>
---
host: host-1
datacenter:
  location: Poland
---
host: host-2
datacenter:
  Location: Spain
... # (optinal) mark end of directive/collection without cloasing the data stream
</source>
= Comments =
<source lang=bash>
# Valid comment1 - must be a space in between '# comment
---
host: host-1 # Inline: valid comment2, comments in the middle are not allowed
datacenter:  # Inline comment3, all inline comments come at the end of line
            # <- any empty lines are read as comments too
  location: Poland
---
host: host-2
datacenter:
  Location: Spain
... #(optimal) mark end of directive/collection without closing the data stream
</source>
= Tags =
Tags provide us with three functions:
* ability to assign a universal resource indicator (URI)
* the ability to assign local tags to that indicator, using eg. <code>! WAW</code>
* change how the YAML parser reads certain scalars when processing the YAML, using eg.<code>!!str</code> (!!) indicator to change the data type of a scalar, used to change a data type
* a custom URI (Universal Resource Indicator). These can be used with PyYAML or other YAML APIs by exposing resources
* to set local tags - reference only within local directive/file
Syntax
<source lang=yaml>
                              # assign a URI header
%TAG ! tag:hostsdata:warsaw:  # syntax: '%TAG ! tag:reference:path'
                              # can use also prefix eg '!foo' but '!' is enough
</source>
Local tags
<source lang=yaml>
# Warsaw DataCentre
%TAG ! tag:hostsdata:warsaw:  # assign a URI header by creating a local-tag-reference-path
host: warsaw-1
datacentre:
  location: !WAW Warsaw        # create a local-tag-reference (assign local tags to URI)
  cab: !!str 11                # changed number to string
# Reference 'location by calling the tag:
tag:hostsdata:warsaw:WAW
</source>
Default data types:
*<code>seq</code> - Sequence
*<code>map</code> - Map
*<code>str</code> - String
*<code>int</code> - Integer
*<code>float</code> - Floating-point decimal
*<code>null</code> - Null
*<code>binary</code> - Binary code
*<code>omap</code> - Ordered map
*<code>set</code> - Unordered set
= Anchors =
* [https://www.mirantis.com/blog/introduction-to-yaml-part-2-kubernetes-services-ingress-and-repeated-nodes/ repeated scalar value building a Kubernetes Service YAML file]
Anchors allow to reuse data across a YAML file.
* <code>&</code> define an anchor by prefix to assign some data a name, you can reuse the name to reassign new values and used itm in different place of the file
* use the <code>*</code> to reference data with that name to call it repeatedly throughout the file
<source lang=yaml>
---
host: waw-1
datacenter:
  location: &WAW Warsaw # set an anchor
  cabinet: !!str 11
roles: &ROLES
# &ROLES it's also accepted in newline, as long there is a space after a ':'
  - web
  - db
---
host: krk-2
datacentre:
  location: *WAW  # reference the anchor, this pull also the comment
  cabinet: !!str 12
roles: *ROLES  # when the file is parsed, data will be pulled from
              # &ROLES anchor
</source>
Override example
<source lang=yaml>
---
master_cipher: &master_cipher
  alias: "default.master"
  plain: "password1"
  passhash: "aaaaaaaaaaaa=="
slave_cipher: &slave_cipher
  alias: "default.slave"
  plain: "password2"
  passhash: "bbbbbbbbbbbb=="
cipher:
  - << : *master_cipher              # '<<' part of syntax, points where data structure will be inserted (anchored)
  - << : *master_cipher              # 'master_cipher' data structure will be expanded here, where
    alias: "default.master.common"  #  'alias' value will get overriden
  - << : *slave_cipher              # 'slave_cipher' data structure will be expanded here
    alias: "default.slave.common"    #  'alias' value will get overriden
</source>
= Gotchas =
<source lang=yaml>
---
country:
  yes: 49.7 # this is boolean as it's YAML recognized world, fix by "yes"
  nah: 50.1
</source>
= References =
* [https://stackoverflow.com/questions/44968474/tool-to-automatically-expand-yaml-mergeshttps://stackoverflow.com/questions/44968474/tool-to-automatically-expand-yaml-merges create DRY -> non-DRY YAML]
* [https://blog.daemonl.com/2016/02/yaml.html Yaml anchors] Quite random find
* [https://yaml-multiline.info/ yaml-multiline]
* [https://stackoverflow.com/questions/3790454/how-do-i-break-a-string-in-yaml-over-multiple-lines How do I break a string in YAML over multiple lines?]
* [https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell The yaml document from hell] ruudvanasseldonk.com

Latest revision as of 00:02, 13 January 2023

Styles

YAML syntax styles
Block style Flow style
Human frendly, less compact An extension of JSON, foldinf long lines, tags and anchors
host: host-1
datacenter:        #mapping
  location: Poland #key-value mapping indentention
  cabinet: 11
roles:             #list
  - web
  - dns
host: "host-1"
datacentrer: { location:
  Poland , cabinet: 11 }
roles: [ web , dns ] 
# {} kv mapping
# [] list (array)

Characters

  • Printable Unicode
  • Unsupported symbols
    • C0/C1 blocks
      • Exceptions: Tab, Line Feed, Carrage Return, Delete, Next line
    • Surrogates
  • Encoding: UTF-8, 16, 32
  • To be JSON compatibile must be UTF-32

Mappings

Mappings are also known as:

  • assosiative arrays
  • hash tables
  • kv pairs
  • collection (YAML specific term, that groups things indented at the same level)
Mappings, the colon-space combination that marks it as a mapping
Block style Flow style
host: host-1
datacenter:
  location: Poland
  cabinet: 11
# cabinet: 12   #the same keys are not allowed
host: host-1
datacentre: { location: Poland, cabinet: 11 }

Sequences (list)

Also known as:

  • Lists, dictionary, arrays or collections
  • Denoted with a dash - and space
  • Can be combined with mappings:
    • mapping of sequences
    • sequence of mapping
    • list of maps


Sequence

host: host-1     # sequence/list of mappings
  - datacenter:
    location: Poland
    cabinet: 11
roles:           # sequence
  - web
  - dns
  - ""  #blank lines are not allowed, thus double-quotes are required


Flow style sequence

roles: [ web, dns, "" ]

Examples of lists and maps

Sequences are lists

- Item 1
- Item 2


Mappings are key-value pairs

key1: value1
key2: value2


A sequence of mappings:

- key1: value1
  key2: value2


A mapping of mappings:

overallkey:
  key1: value1
  key2: value2

Scalars

Scalar is a string, number of boolean with whitespace permitted.

---
host: host-1    
datacenter:
  location: "Poland\n" # double-quotes allow escape sequences, "\n" - will be read as new-line
  cabinet: '11'        # change a number into string single or double-quotes
roles:          
  - web
  - dns
  - ""  #blank lines are not allowed, thus double-quotes are required
comments: | # pipe (multiline scalar) it preserves newlines
  Comment 1 note of the required indent
  Comment 2
comments_other: > # right chevron (folded scalar) does not preserve new lines, but helps with code readibility
                  # converts newlines /spacing into single space.
  Other_comment is that indent is still needed
  Another comment.
<tab><tab> item-1 this preserves new lines to create a list
<tab><tab> item-2

Block Scalars - control multiline string

Check ^^ link above.

Structures

YAML allows for multiple directive/documents in one file. The document/directive starts with --- but it's often optional for single directive files. Ansible requires it but not Salt. The delimiters are reuired for multi-directive files.

---
host: host-1
datacenter:
  location: Poland
---
host: host-2
datacenter:
  Location: Spain
... # (optinal) mark end of directive/collection without cloasing the data stream

Comments

# Valid comment1 - must be a space in between '# comment
---
host: host-1 # Inline: valid comment2, comments in the middle are not allowed
datacenter:  # Inline comment3, all inline comments come at the end of line
             # <- any empty lines are read as comments too 
  location: Poland
---
host: host-2
datacenter:
  Location: Spain
... #(optimal) mark end of directive/collection without closing the data stream

Tags

Tags provide us with three functions:

  • ability to assign a universal resource indicator (URI)
  • the ability to assign local tags to that indicator, using eg. ! WAW
  • change how the YAML parser reads certain scalars when processing the YAML, using eg.!!str (!!) indicator to change the data type of a scalar, used to change a data type
  • a custom URI (Universal Resource Indicator). These can be used with PyYAML or other YAML APIs by exposing resources
  • to set local tags - reference only within local directive/file


Syntax

# assign a URI header
%TAG ! tag:hostsdata:warsaw:  # syntax: '%TAG ! tag:reference:path'
                              # can use also prefix eg '!foo' but '!' is enough


Local tags

# Warsaw DataCentre
%TAG ! tag:hostsdata:warsaw:   # assign a URI header by creating a local-tag-reference-path
host: warsaw-1
datacentre:
  location: !WAW Warsaw        # create a local-tag-reference (assign local tags to URI)
  cab: !!str 11                # changed number to string

# Reference 'location by calling the tag:
tag:hostsdata:warsaw:WAW


Default data types:

  • seq - Sequence
  • map - Map
  • str - String
  • int - Integer
  • float - Floating-point decimal
  • null - Null
  • binary - Binary code
  • omap - Ordered map
  • set - Unordered set

Anchors


Anchors allow to reuse data across a YAML file.

  • & define an anchor by prefix to assign some data a name, you can reuse the name to reassign new values and used itm in different place of the file
  • use the * to reference data with that name to call it repeatedly throughout the file
---
host: waw-1
datacenter:
  location: &WAW Warsaw # set an anchor
  cabinet: !!str 11
roles: &ROLES
# &ROLES it's also accepted in newline, as long there is a space after a ':'
  - web
  - db
---
host: krk-2
datacentre: 
  location: *WAW  # reference the anchor, this pull also the comment
  cabinet: !!str 12
roles: *ROLES  # when the file is parsed, data will be pulled from
               # &ROLES anchor


Override example

---
master_cipher: &master_cipher
  alias: "default.master"
  plain: "password1"
  passhash: "aaaaaaaaaaaa=="
slave_cipher: &slave_cipher
  alias: "default.slave"
  plain: "password2"
  passhash: "bbbbbbbbbbbb=="
cipher:
  - << : *master_cipher              # '<<' part of syntax, points where data structure will be inserted (anchored)
  - << : *master_cipher              # 'master_cipher' data structure will be expanded here, where
    alias: "default.master.common"   #   'alias' value will get overriden
  - << : *slave_cipher               # 'slave_cipher' data structure will be expanded here
    alias: "default.slave.common"    #   'alias' value will get overriden

Gotchas

---
country:
  yes: 49.7 # this is boolean as it's YAML recognized world, fix by "yes"
  nah: 50.1

References