salt/doc/topics/troubleshooting/yaml_idiosyncrasies.rst

275 lines
7.7 KiB
ReStructuredText
Raw Normal View History

===================
YAML Idiosyncrasies
===================
One of Salt's strengths, the use of existing serialization systems for
2012-05-23 04:43:12 +00:00
representing SLS data, can also backfire. `YAML`_ is a general purpose system
and there are a number of things that would seem to make sense in an sls
file that cause YAML issues. It is wise to be aware of these issues. While
reports or running into them are generally rare they can still crop up at
unexpected times.
2012-05-23 04:43:12 +00:00
.. _`YAML`: http://yaml.org/spec/1.1/
Spaces vs Tabs
==============
2012-05-23 04:43:12 +00:00
`YAML uses spaces`_, period. Do not use tabs in your SLS files! If strange
errors are coming up in rendering SLS files, make sure to check that
no tabs have crept in! In Vim, after enabling search highlighting
with: ``:set hlsearch``, you can check with the following key sequence in
normal mode(you can hit `ESC` twice to be sure): ``/``, `Ctrl-v`, `Tab`, then
hit `Enter`. Also, you can convert tabs to 2 spaces by these commands in Vim:
``:set tabstop=2 expandtab`` and then ``:retab``.
2012-05-23 04:43:12 +00:00
.. _`YAML uses spaces`: http://yaml.org/spec/1.1/#id871998
Indentation
===========
The suggested syntax for YAML files is to use 2 spaces for indentation,
but YAML will follow whatever indentation system that the individual file
2012-05-23 04:43:12 +00:00
uses. Indentation of two spaces works very well for SLS files given the
fact that the data is uniform and not deeply nested.
.. _nested-dict-indentation:
Nested Dicts (key=value)
------------------------
When :ref:`dicts <python2:typesmapping>` are more deeply nested, they no longer
follow the same indentation logic. This is rarely something that comes up in
Salt, since deeply nested options like these are discouraged when making State
modules, but some do exist. A good example of this can be found in the
``context`` and ``default`` options from the :doc:`file.managed
</ref/states/all/salt.states.file>` state:
.. code-block:: yaml
/etc/http/conf/http.conf:
file:
- managed
- source: salt://apache/http.conf
- user: root
- group: root
- mode: 644
- template: jinja
- context:
custom_var: "override"
- defaults:
custom_var: "default value"
other_var: 123
Notice that while the indentation is two spaces per level, for the values under
the ``context`` and ``defaults`` options there is a four-space indent. If only
two spaces are used to indent, then the information will not be loaded
correctly. If using a double indent is not desirable, then a deeply-nested dict
can be declared with curly braces:
.. code-block:: yaml
/etc/http/conf/http.conf:
file:
- managed
- source: salt://apache/http.conf
- user: root
- group: root
- mode: 644
- template: jinja
- context: {
custom_var: "override" }
- defaults: {
2012-05-01 18:04:41 +00:00
custom_var: "default value",
other_var: 123 }
2012-05-23 04:43:12 +00:00
True/False, Yes/No, On/Off
==========================
PyYAML will load these values as boolean ``True`` or ``False``. Un-capitalized
versions will also be loaded as booleans (``true``, ``false``, ``yes``, ``no``,
``on``, and ``off``). This can be especially problematic when constructing
Pillar data. Make sure that your Pillars which need to use the string versions
of these values are enclosed in quotes.
Integers are Parsed as Integers
===============================
2012-08-20 21:38:38 +00:00
NOTE: This has been fixed in salt 0.10.0, as of this release passing an
integer that is preceded by a 0 will be correctly parsed
When passing :func:`integers <python2:int>` into an SLS file, they are
passed as integers. This means that if a state accepts a string value
and an integer is passed, that an integer will be sent. The solution here
is to send the integer as a string.
This is best explained when setting the mode for a file:
.. code-block:: yaml
/etc/vimrc:
file:
- managed
- source: salt://edit/vimrc
- user: root
- group: root
- mode: 644
Salt manages this well, since the mode is passed as 644, but if the mode is
zero padded as 0644, then it is read by YAML as an integer and evaluated as
2012-08-20 20:15:04 +00:00
an octal value, 0644 becomes 420. Therefore, if the file mode is
preceded by a 0 then it needs to be passed as a string:
.. code-block:: yaml
/etc/vimrc:
file:
- managed
- source: salt://edit/vimrc
- user: root
- group: root
- mode: '0644'
2013-07-09 16:12:38 +00:00
2012-04-23 06:33:57 +00:00
2012-05-23 04:43:12 +00:00
YAML does not like "Double Short Decs"
2012-04-23 06:33:57 +00:00
======================================
2012-05-23 04:43:12 +00:00
If I can find a way to make YAML accept "Double Short Decs" then I will, since
2012-04-23 06:33:57 +00:00
I think that double short decs would be awesome. So what is a "Double Short
Dec"? It is when you declare a multiple short decs in one ID. Here is a
standard short dec, it works great:
.. code-block:: yaml
vim:
pkg.installed
The short dec means that there are no arguments to pass, so it is not required
to add any arguments, and it can save space.
2012-05-23 04:43:12 +00:00
YAML though, gets upset when declaring multiple short decs, for the record...
2012-04-23 06:33:57 +00:00
THIS DOES NOT WORK:
.. code-block:: yaml
vim:
pkg.installed
user.present
Similarly declaring a short dec in the same ID dec as a standard dec does not
work either...
ALSO DOES NOT WORK:
.. code-block:: yaml
fred:
user.present
ssh_auth.present:
2012-04-23 06:33:57 +00:00
- name: AAAAB3NzaC...
- user: fred
- enc: ssh-dss
- require:
- user: fred
2012-04-23 06:33:57 +00:00
The correct way is to define them like this:
2012-04-23 06:33:57 +00:00
.. code-block:: yaml
vim:
pkg.installed: []
user.present: []
fred:
user.present: []
ssh_auth.present:
- name: AAAAB3NzaC...
- user: fred
- enc: ssh-dss
- require:
- user: fred
Alternatively, they can be defined the "old way", or with multiple
"full decs":
2012-04-23 06:33:57 +00:00
.. code-block:: yaml
vim:
pkg:
- installed
user:
- present
fred:
user:
- present
ssh_auth:
- present
2012-04-23 06:33:57 +00:00
- name: AAAAB3NzaC...
- user: fred
- enc: ssh-dss
- require:
- user: fred
2012-04-23 06:33:57 +00:00
YAML support only plain ASCII
=============================
2012-08-29 16:41:39 +00:00
According to YAML specification, only ASCII characters can be used.
Within double-quotes, special characters may be represented with C-style
escape sequences starting with a backslash ( \\ ).
Examples:
.. code-block:: yaml
- micro: "\u00b5"
- copyright: "\u00A9"
- A: "\x41"
- alpha: "\u0251"
- Alef: "\u05d0"
2012-08-29 16:41:39 +00:00
2013-07-09 16:12:38 +00:00
List of usable `Unicode characters`_ will help you to identify correct numbers.
.. _`Unicode characters`: http://en.wikipedia.org/wiki/List_of_Unicode_characters
2012-08-29 16:41:39 +00:00
Python can also be used to discover the Unicode number for a character:
.. code-block:: python
repr(u"Text with wrong characters i need to figure out")
2012-08-29 16:41:39 +00:00
This shell command can find wrong characters in your SLS files:
.. code-block:: bash
find . -name '*.sls' -exec grep --color='auto' -P -n '[^\x00-\x7F]' \{} \;
Alternatively you can toggle the `yaml_utf8` setting in your master configuration
file. This is still an experimental setting but it should manage the right
encoding conversion in salt after yaml states compilations.
Underscores stripped in Integer Definitions
===========================================
If a definition only includes numbers and underscores, it is parsed by YAML as
an integer and all underscores are stripped. To ensure the object becomes a
string, it should be surrounded by quotes. `More information here`_.
.. _`More information here`: http://stackoverflow.com/questions/2723321/snakeyaml-how-to-disable-underscore-stripping-when-parsing
Here's an example:
.. code-block:: python
>>> import yaml
>>> yaml.safe_load('2013_05_10')
20130510
>>> yaml.safe_load('"2013_05_10"')
'2013_05_10'