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.