Document type stdin inside loop caveats
This commit is contained in:
		
					parent
					
						
							
								520cfeda98
							
						
					
				
			
			
				commit
				
					
						68837e45cc
					
				
			
		
					 2 changed files with 68 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -4,6 +4,7 @@ Changelog
 | 
			
		|||
next:
 | 
			
		||||
	* Type __apt_key: Use gpg key, fallback to deprecated apt-key (Ander Punnar)
 | 
			
		||||
	* Type __acl: Fix and improve (Ander Punnar)
 | 
			
		||||
	* Documentation: Document type stdin inside loop caveats (Darko Poljak)
 | 
			
		||||
 | 
			
		||||
5.1.0: 2019-05-22
 | 
			
		||||
	* Type __consul: Add alpine support (Nico Schottelius)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,6 +216,73 @@ In the __file type, stdin is used as source for the file, if - is used for sourc
 | 
			
		|||
    ....
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Stdin inside a loop
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
Since cdist saves type's stdin content in the object as **$__object/stdin**,
 | 
			
		||||
so it can be accessed in manifest and gencode-* scripts, this can lead to
 | 
			
		||||
unexpected behavior. For example, suppose you have some type with the following
 | 
			
		||||
in its manifest:
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    if [ -f "$__object/parameter/foo" ]
 | 
			
		||||
    then
 | 
			
		||||
        while read -r l
 | 
			
		||||
        do
 | 
			
		||||
            __file "$l"
 | 
			
		||||
            echo "$l" >&2
 | 
			
		||||
        done < "$__object/parameter/foo"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
and init manifest:
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    __foo foo --foo a --foo b --foo c
 | 
			
		||||
 | 
			
		||||
You expect that manifest stderr content is:
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    a
 | 
			
		||||
    b
 | 
			
		||||
    c
 | 
			
		||||
 | 
			
		||||
and that files *a*, *b* and *c* are created. But all you get in manifest stderr
 | 
			
		||||
is:
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    a
 | 
			
		||||
 | 
			
		||||
and only *a* file is created.
 | 
			
		||||
 | 
			
		||||
When redirecting parameter *foo* file content to while's stdin that means that all
 | 
			
		||||
commands in while body have this same stdin. So when *__file* type gets executed,
 | 
			
		||||
cdist saves its stdin which means it gets the remaining content of parameter *foo*
 | 
			
		||||
file, i.e.:
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    b
 | 
			
		||||
    c
 | 
			
		||||
 | 
			
		||||
The solution is to make sure that your types inside such loops get their stdin
 | 
			
		||||
from somewhere else, e.g. for the above problem *__file* type can get empty
 | 
			
		||||
stdin from */dev/null*:
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    if [ -f "$__object/parameter/foo" ]
 | 
			
		||||
    then
 | 
			
		||||
        while read -r l
 | 
			
		||||
        do
 | 
			
		||||
            __file "$l" < /dev/null
 | 
			
		||||
            echo "$l" >&2
 | 
			
		||||
        done < "$__object/parameter/foo"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Writing the manifest
 | 
			
		||||
--------------------
 | 
			
		||||
In the manifest of a type you can use other types, so your type extends
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue