Jacob McCoy Wade
2013-Aug-01 19:37 UTC
[Puppet Users] escape sequence within generate function
I''m looking for some help in getting the proper escape sequence within the generate function. Ultimately what I''m trying to do is generate some random strings, store them as variables, and use those variables to populate configuration files stored as templates. I can get this to work when applying the template on the localhost, but it fails when applied via the puppet master.:> $random_1 = generate("/bin/sh", "-c", "/bin/cat /dev/urandom | /usr/bin/tr- > dc ''a-z0-9'' | /usr/bin/fold -w 8 | /usr/bin/head -n 1 | /usr/bin/tr -d > ''\n''")The closest I''ve come is to use:> $random_1 = generate(''/bin/sh'', ''-c'', ''\"/bin/cat /dev/urandom | /usr/bin/ > tr -dc \''a-z0-9\'' | /usr/bin/fold -w 8 | /usr/bin/head -n 1 | /usr/bin/tr-d \''\n\''\"'' > )This however ends up populating the variable with the following and appears to ignore the the "/usr/bin/tr -d ''\n''" as there are line breaks inserted:> /bin/sh: "/bin/cat: No such file or directory >What I''m really wanting (I think) to be executed on the puppet master is> "/bin/sh" "-c" "/bin/cat /dev/urandom | /usr/bin/tr -dc ''a-z0-9'' | > /usr/bin/fold -w 8 | /usr/bin/head -n 1 | /usr/bin/tr -d ''\n''"Any help would be appreciated. -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users+unsubscribe@googlegroups.com. To post to this group, send email to puppet-users@googlegroups.com. Visit this group at http://groups.google.com/group/puppet-users. For more options, visit https://groups.google.com/groups/opt_out.
jcbollinger
2013-Aug-02 13:43 UTC
[Puppet Users] Re: escape sequence within generate function
On Thursday, August 1, 2013 2:37:03 PM UTC-5, Jacob McCoy Wade wrote:> > I''m looking for some help in getting the proper escape sequence within the > generate function. > Ultimately what I''m trying to do is generate some random strings, store > them as variables, and use those variables to populate configuration files > stored as templates. > I can get this to work when applying the template on the localhost, but it > fails when applied via the puppet master.: > >> $random_1 = generate("/bin/sh", "-c", "/bin/cat /dev/urandom | /usr/bin/ >> tr -dc ''a-z0-9'' | /usr/bin/fold -w 8 | /usr/bin/head -n 1 | /usr/bin/tr-d ''\n''" >> ) > > > The closest I''ve come is to use: > >> $random_1 = generate(''/bin/sh'', ''-c'', ''\"/bin/cat /dev/urandom | /usr >> /bin/tr -dc \''a-z0-9\'' | /usr/bin/fold -w 8 | /usr/bin/head -n 1 | /usr >> /bin/tr -d \''\n\''\"'') > > > This however ends up populating the variable with the following and > appears to ignore the the "/usr/bin/tr -d ''\n''" as there are line breaks > inserted: > >> /bin/sh: "/bin/cat: No such file or directory >> > >So, that''s the wrong thing to do, because ''cat'' will keep reading its input until it reaches the end, which it never will in this case. It may be that having ''head'' in the pipeline would rescue it by closing its own input, but you might end up with a bunch of stalled, orphaned processes. You should instead use /bin/dd or some other command that allows you to limit the amount of data read from /dev/urandom. But that brings us to the next problem: The output you see on the master appears to be telling you that the file you are trying to cat (/dev/urandom) does not exist there. Possibly it''s there, but it or its parent directory is not readable by Puppet. Unless you can sort that out, you will need an altogether different approach.> What I''m really wanting (I think) to be executed on the puppet master is > >> "/bin/sh" "-c" "/bin/cat /dev/urandom | /usr/bin/tr -dc ''a-z0-9'' | >> /usr/bin/fold -w 8 | /usr/bin/head -n 1 | /usr/bin/tr -d ''\n''" > > > Any help would be appreciated. >There is also a third, more fundamental problem: it is unlikely that you really want to do what you are trying to do. If you generate a completely random component to a config file on every run, then that file will never match from one run to the next, so it will always be re-synced. That is rarely the intent. More often, you want different, random strings for each node, but you want those strings to be stable from run to run for any given node. One way to achieve that might be to construct strings as the concatenation of a constant stem and a random number generated via Puppet''s built-in fqdn_rand() function. Even if that would not be sufficient, I have trouble seeing why it makes sense to use generate() for this purpose. It would be not only lighter-weight but also more flexible to use Ruby''s rand() function via Puppet''s inline_template() function. You could even use fqdn_rand() to seed the Ruby RNG, so as to get a broader range of consistent pseudorandom values. And, you would have as much control as you want over the random data -- such as, for instance, ensuring that it does not contain null (0) bytes. As for the question in your title, to insert the literal two-character sequence ''\n'' into a double-quoted Puppet string, escape the backslash by doubling it: "... /usr/bin/tr -d ''\\n''". (See http://docs.puppetlabs.com/puppet/3/reference/lang_datatypes.html#strings.) Note that only the outermost quotes affect what escape sequences are recognized; the inner single quotes in your string are just ordinary characters to Puppet. John -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users+unsubscribe@googlegroups.com. To post to this group, send email to puppet-users@googlegroups.com. Visit this group at http://groups.google.com/group/puppet-users. For more options, visit https://groups.google.com/groups/opt_out.
Jacob McCoy Wade
2013-Aug-02 17:07 UTC
[Puppet Users] Re: escape sequence within generate function
On Friday, August 2, 2013 6:43:01 AM UTC-7, jcbollinger wrote:> > > > On Thursday, August 1, 2013 2:37:03 PM UTC-5, Jacob McCoy Wade wrote: >> >> The closest I''ve come is to use: >> >>> $random_1 = generate(''/bin/sh'', ''-c'', ''\"/bin/cat /dev/urandom | /usr >>> /bin/tr -dc \''a-z0-9\'' | /usr/bin/fold -w 8 | /usr/bin/head -n 1 | /usr >>> /bin/tr -d \''\n\''\"'') >> >> >> This however ends up populating the variable with the following and >> appears to ignore the the "/usr/bin/tr -d ''\n''" as there are line breaks >> inserted: >> >>> /bin/sh: "/bin/cat: No such file or directory >>> >> >> > So, that''s the wrong thing to do, because ''cat'' will keep reading its > input until it reaches the end, which it never will in this case. It may > be that having ''head'' in the pipeline would rescue it by closing its own > input, but you might end up with a bunch of stalled, orphaned processes. > You should instead use /bin/dd or some other command that allows you to > limit the amount of data read from /dev/urandom. > > I was using head to close the input. The other thing I can''t quite makesense of is why it works when I apply the module directly on the node, but not when using a puppet master.> There is also a third, more fundamental problem: it is unlikely that you > really want to do what you are trying to do. If you generate a completely > random component to a config file on every run, then that file will never > match from one run to the next, so it will always be re-synced. That is > rarely the intent. More often, you want different, random strings for each > node, but you want those strings to be stable from run to run for any given > node. One way to achieve that might be to construct strings as the > concatenation of a constant stem and a random number generated via Puppet''s > built-in fqdn_rand() function. > > I was thinking that I could use "replace => ''no''," within the module sothat puppet won''t re-sync the file every run.> Even if that would not be sufficient, I have trouble seeing why it makes > sense to use generate() for this purpose. It would be not only > lighter-weight but also more flexible to use Ruby''s rand() function via > Puppet''s inline_template() function. You could even use fqdn_rand() to > seed the Ruby RNG, so as to get a broader range of consistent pseudorandom > values. And, you would have as much control as you want over the random > data -- such as, for instance, ensuring that it does not contain null (0) > bytes. > > I''ve yet to use the inline_template() function and am not fluent enough inRuby to know how to use the rand() function, but it sounds like it might be time to learn how :)> As for the question in your title, to insert the literal two-character > sequence ''\n'' into a double-quoted Puppet string, escape the backslash by > doubling it: "... /usr/bin/tr -d ''\\n''". (See > http://docs.puppetlabs.com/puppet/3/reference/lang_datatypes.html#strings.) > Note that only the outermost quotes affect what escape sequences are > recognized; the inner single quotes in your string are just ordinary > characters to Puppet. >That helps me at least understand about escape sequencing in Puppet. The other issue with using the generate() function is that I run in to either "Generators must be fully qualified" or "Generators can only contain alphanumerics, file separators, and dashes". More proof that it''s time to give up on trying to make the generator() function work for this purpose. Thanks for the help. -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users+unsubscribe@googlegroups.com. To post to this group, send email to puppet-users@googlegroups.com. Visit this group at http://groups.google.com/group/puppet-users. For more options, visit https://groups.google.com/groups/opt_out.
jcbollinger
2013-Aug-05 13:27 UTC
[Puppet Users] Re: escape sequence within generate function
On Friday, August 2, 2013 12:07:24 PM UTC-5, Jacob McCoy Wade wrote:> > > > On Friday, August 2, 2013 6:43:01 AM UTC-7, jcbollinger wrote: >> >> >> >> On Thursday, August 1, 2013 2:37:03 PM UTC-5, Jacob McCoy Wade wrote: >>> >>> The closest I''ve come is to use: >>> >>>> $random_1 = generate(''/bin/sh'', ''-c'', ''\"/bin/cat /dev/urandom | /usr >>>> /bin/tr -dc \''a-z0-9\'' | /usr/bin/fold -w 8 | /usr/bin/head -n 1 | /usr >>>> /bin/tr -d \''\n\''\"'') >>> >>> >>> This however ends up populating the variable with the following and >>> appears to ignore the the "/usr/bin/tr -d ''\n''" as there are line breaks >>> inserted: >>> >>>> /bin/sh: "/bin/cat: No such file or directory >>>> >>> >>> >> So, that''s the wrong thing to do, because ''cat'' will keep reading its >> input until it reaches the end, which it never will in this case. It may >> be that having ''head'' in the pipeline would rescue it by closing its own >> input, but you might end up with a bunch of stalled, orphaned processes. >> You should instead use /bin/dd or some other command that allows you to >> limit the amount of data read from /dev/urandom. >> >> I was using head to close the input. The other thing I can''t quite make > sense of is why it works when I apply the module directly on the node, but > not when using a puppet master. >Like all Puppet functions, generate() runs on machine where the catalog is compiled, not on the one where it is applied, unless they are the same. It appears that the master you are using does not have (a Puppet-accessible) /dev/urandom, whereas the target node has one that is accessible to the user as whom you are running ''puppet apply''.> > >> There is also a third, more fundamental problem: it is unlikely that you >> really want to do what you are trying to do. If you generate a completely >> random component to a config file on every run, then that file will never >> match from one run to the next, so it will always be re-synced. That is >> rarely the intent. More often, you want different, random strings for each >> node, but you want those strings to be stable from run to run for any given >> node. One way to achieve that might be to construct strings as the >> concatenation of a constant stem and a random number generated via Puppet''s >> built-in fqdn_rand() function. >> >> I was thinking that I could use "replace => ''no''," within the module so > that puppet won''t re-sync the file every run. >You could, though by doing so you give up the ability to have Puppet keep the file synced to your spec. Replace => ''no'' is most appropriately applied to files that are expected to be modified in the course of their normal use, however, to prevent Puppet from clobbering the modifications. Inasmuch the only reason for using it here seems to be to facilitate using /dev/urandom as the source of randomness, and as using /dev/urandom for this purpose appears inferior in most ways to using Puppet''s and/or Ruby''s built-in sources of randomness, I really don''t see the point. John -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to puppet-users+unsubscribe@googlegroups.com. To post to this group, send email to puppet-users@googlegroups.com. Visit this group at http://groups.google.com/group/puppet-users. For more options, visit https://groups.google.com/groups/opt_out.
Apparently Analagous Threads
- How to include the Scope(...) in a generated string?
- How to escape exec command parameters?
- Hash Interpolation inside double quotes?
- inline_template private method `gets' called for false:FalseClass
- err: Could not retrieve catalog from remote server: Could not intern from pson: Could not convert from pson: Could not find relationship target "File[]"