John,

Thanks for the reply.  To answer your first question, no I'm not completely 
sure.  What I can say is that I can run the commands in a shell by hand and 
the result is what I hope for.  When I run puppet, with this particular 
class included, puppet hangs for a while with no screen output.  This leads 
me to believe that the "unless" fails and the "command" executes.  I can 
verify that by running (in another shell):

[root@desktop ~]# ps -ef|grep aide
root     28085     1  0 14:42 ?        00:00:00 sh -c /usr/sbin/aide --init 
>/dev/null 2>&1 && cp -p ${DBDIR}/${DBNEW} ${DBDIR}/${DBFILE}
root     28088 28085 20 14:42 ?        00:01:24 /usr/sbin/aide --init


I can say when I run the various piece by hand inside an interactive shell 
everything comes out as expected:

[root@desktop ~]# DBDIR=$(egrep '^@@define DBDIR ' /etc/aide.conf |awk 
'{print $NF}')
[root@desktop ~]# echo $DBDIR
/var/lib/aide
[root@desktop ~]# DBFILE=$(egrep '^database=file' /etc/aide.conf |awk -F/ 
'{print $NF}')
[root@desktop ~]# echo $DBFILE
aide.db.gz
[root@desktop ~]# DBNEW=$(egrep '^database_out=file' /etc/aide.conf |awk 
-F/ '{print $NF}')
[root@desktop ~]# echo $DBNEW
aide.db.new.gz
[root@desktop ~]# test -f ${DBDIR}/${DBNEW} && test -f ${DBDIR}/${DBFILE}
[root@desktop ~]# echo $?
0
[root@desktop ~]# /usr/sbin/aide --init >/dev/null 2>&1 && cp -p 
${DBDIR}/${DBNEW} ${DBDIR}/${DBFILE}
cp: overwrite ‘/var/lib/aide/aide.db.gz’? y

The cp overwrite prompt above comes from the alias cp='cp -i ' in my shell. 
 I'm not sure if that would be there inside puppet, but if so I'll modify 
to negate that option.

For testing, I created a separate class for just this one exec.  I modified 
the unless and command statements as follows:

    command     => 'echo "/usr/sbin/aide --init >/dev/null 2>&1 && cp -p 
${DBDIR}/${DBNEW} ${DBDIR}/${DBFILE}"',
    unless      => 'echo "test -f ${DBDIR}/${DBNEW} && test -f 
${DBDIR}/${DBFILE}" && test -f ${DBDIR}/${DBNEW} && test -f 
${DBDIR}/${DBFILE}',

So basically the "unless" echo's what it's doing, then tries to do it.  The 
"command" just echoes what it would do.  Here's the puppet agent --test 
--debug output for the class:

Debug: Exec[init-aide-database](provider=posix): Executing check 'echo 
"test -f ${DBDIR}/${DBNEW} && test -f ${DBDIR}/${DBFILE}" && test -f 
${DBDIR}/${DBNEW} && test -f ${DBDIR}/${DBFILE}'
Debug: Executing 'echo "test -f ${DBDIR}/${DBNEW} && test -f 
${DBDIR}/${DBFILE}" && test -f ${DBDIR}/${DBNEW} && test -f 
${DBDIR}/${DBFILE}'
Debug: /Stage[main]/Testenv/Exec[init-aide-database]/unless: test -f $(egrep 
'^@@define DBDIR ' /etc/aide.conf|awk '{print $NF}')/$(egrep 
'^database_out=file' /etc/aide.conf|awk -F/ '{print $NF}') && test -f $(egrep 
'^@@define DBDIR ' /etc/aide.conf|awk '{print $NF}')/$(egrep 
'^database=file' /etc/aide.conf|awk -F/ '{print $NF}')
Debug: /Stage[main]/Testenv/Exec[init-aide-database]/unless: sh: line 0: 
test: too many arguments
Debug: Exec[init-aide-database](provider=posix): Executing 'echo 
"/usr/sbin/aide --init >/dev/null 2>&1 && cp -p ${DBDIR}/${DBNEW} 
${DBDIR}/${DBFILE}"'
Debug: Executing 'echo "/usr/sbin/aide --init >/dev/null 2>&1 && cp -p 
${DBDIR}/${DBNEW} ${DBDIR}/${DBFILE}"'
Notice: /Stage[main]/Testenv/Exec[init-aide-database]/returns: /usr/sbin/aide 
--init >/dev/null 2>&1 && cp -p $(egrep '^@@define DBDIR ' /etc/aide.conf|awk 
'{print $NF}')/$(egrep '^database_out=file' /etc/aide.conf|awk -F/ '{print 
$NF}') $(egrep '^@@define DBDIR ' /etc/aide.conf|awk '{print $NF}')/$(egrep 
'^database=file' /etc/aide.conf|awk -F/ '{print $NF}')
Notice: /Stage[main]/Testenv/Exec[init-aide-database]/returns: executed 
successfully
Debug: /Stage[main]/Testenv/Exec[init-aide-database]: The container Class[
Testenv] will propagate my refresh event
Debug: Class[Testenv]: The container Stage[main] will propagate my refresh 
event

So it looks like the strings inside the environment variables aren't 
interpreted by the shell, they're just passed as literal strings.  But 
notably, the the unless test fails with an error from /usr/bin/test that 
doesn't surface when running interactively.  I will attempt to run in the 
shell provider instead of posix, but if that fails, I just re-code 
everything into shell scripts and have puppet push and execute them.  If we 
need to make this a bug, I'll be happy to help, but I'm running on EL7 with 
puppet out of EPEL7, with no intent of going to Puppet 4 anytime soon.

Thanks again for taking a look!

On Monday, December 7, 2015 at 11:37:19 AM UTC-5, jcbollinger wrote:
>
>
>
> On Friday, December 4, 2015 at 10:27:52 AM UTC-6, Sean wrote:
>>
>> Greetings,
>>
>> I am working on streamlining some older puppet code, that uses a lot of 
>> Exec resources to accomplish it's purposes.  It's not terribly elegant and 
>> we're working on design to replace it with code that leverages puppet 
>> features.  One of the pieces I'm struggling with is how to set complex 
>> environment variables that are available to use in onlyif/unless statements 
>> as well as the command itself.  I'm wondering if this just isn't possible?
>>
>> Here's an example with the aide.  NOTE that we're not in a spot where I 
>> can make puppet manage the aide config file, and thus use an aide module 
>> and parameters instead of shell variables.  All of these commands run 
>> successfully in a bash shell for the various conditions that would apply. 
>>  I have other similar scenarios, but aide is one of the more complex ones.
>>
>>   exec { 'init-aide-database':
>>     path        => 
>> '/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin',
>>     environment => [ 'DBDIR=$(egrep \'^@@define DBDIR \' 
>> /etc/aide.conf|awk \'{print $NF}\')',
>>       'DBFILE=$(egrep \'^database=file\' /etc/aide.conf|awk -F/ \'{print 
>> $NF}\')',
>>       'DBNEW=$(egrep \'^database_out=file\' /etc/aide.conf|awk -F/ 
>> \'{print $NF}\')',
>>       ],
>>     command     => '/usr/sbin/aide --init >/dev/null 2>&1 && cp -p 
>> ${DBDIR}/${DBNEW} ${DBDIR}/${DBFILE}',
>>     unless      => 'test -f ${DBDIR}/${DBNEW} && test -f 
>> ${DBDIR}/${DBFILE}',
>>     require     => Package['aide'],
>>     logoutput   => true,
>>     timeout     => 0,
>>   }
>>
>> When executing, puppet always runs the exec because the env var's are 
>> empty, so the unless case always fails.  Then we get a scenario where we're 
>> running aide --init when it's not needed and the cp command throws an error 
>> due to empty variables.
>>
>>
>
> Are you sure?  I'd be inclined to suppose that the problem was that the 
> environment variables don't have the values you expect them to have.  As 
> far as I am aware, Puppet inserts environment variables into child 
> processes' environments via a mechanism that does not involve evaluating 
> the value expressions via the shell (even when you use the 'shell' 
> provider).
>
> I had thought that the same environment is presented to the 'unless' and 
> 'onlyif' commands as is presented to the main command, but I can't 
> immediately back that up, as the documentation is at best unclear on that 
> point.  If you could establish that it is not, then that might justify 
> filing a ticket.
>
>  
>
>> My thought at the moment is that I need to build two shell scripts as 
>> file resources.  One to call in the unless test, and another to call in the 
>> command if the unless script fails.  Perhaps that's more elegant, but we're 
>> hoping to avoid delivering script files to the nodes wherever possible. 
>>  I'm hoping the gurus out here might point me in the best direction!
>>
>
>
> If you must determine the needed values for your environment variables at 
> run time, by executing shell code, then I'm pretty confident that one way 
> or another you will need to build that in to each of the commands you use.  
> The approach you describe is a reasonable way to do that.
>
> You could also consider whether it would be worth the effort to build a 
> full-fledged custom type.  You would still need to perform some environment 
> mangling, but you could at least avoid managing separate command scripts.
>
>
> 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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/puppet-users/8d03d36f-adca-47db-9967-d05d8889829b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to