From 8ccb44aa6389386a531081b3253d5f2a448f853b Mon Sep 17 00:00:00 2001 From: Brian Coca Date: Wed, 7 Nov 2018 15:19:23 -0500 Subject: [PATCH] clarify insane ini typing (#48169) * clarify how variables are interpreted in the ini inventory plugin --- .../rst/user_guide/intro_inventory.rst | 12 +++++---- lib/ansible/plugins/inventory/ini.py | 25 +++++++++++-------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/docs/docsite/rst/user_guide/intro_inventory.rst b/docs/docsite/rst/user_guide/intro_inventory.rst index e2c62fc239b..aa1c5f13240 100644 --- a/docs/docsite/rst/user_guide/intro_inventory.rst +++ b/docs/docsite/rst/user_guide/intro_inventory.rst @@ -94,9 +94,12 @@ In the above example, trying to ansible against the host alias "jumper" (which m Note that this is using a feature of the inventory file to define some special variables. Generally speaking, this is not the best way to define variables that describe your system policy, but we'll share suggestions on doing this later. -.. note:: Values passed in the INI format using the ``key=value`` syntax are not interpreted as Python literal structure - (strings, numbers, tuples, lists, dicts, booleans, None), but as a string. For example ``var=FALSE`` would create a string equal to 'FALSE'. - Do not rely on types set during definition, always make sure you specify type with a filter when needed when consuming the variable. +.. note:: Values passed in the INI format using the ``key=value`` syntax are interpreted differently depending on where they are declared. + * When declared inline with the host, INI values are interpreted as Python literal structures + (strings, numbers, tuples, lists, dicts, booleans, None). Host lines accept multiple ``key=value`` parameters per line. Therefore they need a way to indicate that a space is part of a value rather than a separator. + * When declared in a ``:vars`` section, INI values are interpreted as strings. For example ``var=FALSE`` would create a string equal to 'FALSE'. Unlike host lines, ``:vars`` sections accept only a single entry per line, so everything after the ``=`` must be the value for the entry. + * Do not rely on types set during definition, always make sure you specify type with a filter when needed when consuming the variable. + * Consider using YAML format for inventory sources to avoid confusion on the actual type of a variable. The YAML inventory plugin processes variable values consistently and correctly. If you are adding a lot of hosts following similar patterns, you can do this rather than listing each hostname: @@ -140,7 +143,7 @@ As described above, it is easy to assign variables to hosts that will be used la The YAML version: .. code-block:: yaml - + atlanta: host1: http_port: 80 @@ -502,4 +505,3 @@ Here is an example of how to instantly deploy to created containers:: Questions? Help? Ideas? Stop by the list on Google Groups `irc.freenode.net `_ #ansible IRC chat channel - diff --git a/lib/ansible/plugins/inventory/ini.py b/lib/ansible/plugins/inventory/ini.py index fe7f4cccf4f..8b63a18e65e 100644 --- a/lib/ansible/plugins/inventory/ini.py +++ b/lib/ansible/plugins/inventory/ini.py @@ -14,15 +14,20 @@ DOCUMENTATION = ''' - The C(children) modifier indicates that the section contains groups. - The C(vars) modifier indicates that the section contains variables assigned to members of the group. - Anything found outside a section is considered an 'ungrouped' host. - - Values passed in using the C(key=value) syntax are interpreted as Python literal structure (strings, numbers, tuples, lists, dicts, - booleans, None), alternatively as string. For example C(var=FALSE) would create a string equal to 'FALSE'. Do not rely on types set - during definition, always make sure you specify type with a filter when needed when consuming the variable. + - Values passed in the INI format using the ``key=value`` syntax are interpreted differently depending on where they are declared within your inventory. + - When declared inline with the host, INI values are are processed by Python's ast.literal_eval function + (U(https://docs.python.org/2/library/ast.html#ast.literal_eval)) and interpreted as Python literal structures + (strings, numbers, tuples, lists, dicts, booleans, None). Host lines accept multiple C(key=value) parameters per line. + Therefore they need a way to indicate that a space is part of a value rather than a separator. + - When declared in a C(:vars) section, INI values are interpreted as strings. For example C(var=FALSE) would create a string equal to C(FALSE). + Unlike host lines, C(:vars) sections accept only a single entry per line, so everything after the C(=) must be the value for the entry. + - Do not rely on types set during definition, always make sure you specify type with a filter when needed when consuming the variable. + - See the Examples for proper quoting to prevent changes to variable type. notes: - - It takes the place of the previously hardcoded INI inventory. - - To function it requires being whitelisted in configuration. - - Variable values are processed by Python's ast.literal_eval function (U(https://docs.python.org/2/library/ast.html#ast.literal_eval)) - which could cause the value to change in some cases. See the Examples for proper quoting to prevent changes. Another option would be - to use the yaml format for inventory source which processes the values correctly. + - Replaces the previously hardcoded INI inventory. + - Must be whitelisted in configuration to function. + - Consider switching to YAML format for inventory sources to avoid confusion on the actual type of a variable. + The YAML inventory plugin processes variable values consistently and correctly. ''' EXAMPLES = ''' @@ -30,11 +35,11 @@ EXAMPLES = ''' # example cfg file [web] host1 - host2 ansible_port=222 + host2 ansible_port=222 # defined inline, interpreted as an integer [web:vars] http_port=8080 # all members of 'web' will inherit these - myvar=23 + myvar=23 # defined in a :vars section, interpreted as a string [web:children] # child groups will automatically add their hosts to partent group apache