Puppet not executing command. Getting stuck and giving timeout - linux

exec { "stop old application instance":
cwd => "${install_dir}",
path => ['/usr/bin','/bin','/usr/sbin','/sbin', '/bin/unlink', '/usr/local', '/usr/local/bin/'],
onlyif => "test -e '${install_dir}/${app_package_dir}/processes.json'",
group => 0,
user => 'root',
command => "pm2 delete /var/lib/application_folder/processes.json"
}
Puppet is getting stuck here and not able to execute the command. Not understanding the reason. Error log is given bellow
Error: Command exceeded timeout
Wrapped exception:
execution expired
Error: /Stage[main]/application::Install/Exec[stop old application instance]/returns: change from notrun to 0 failed: Command exceeded timeout
Any help will be much appreciated.

https://ask.puppet.com/question/1308/command-exceeded-timeout/
Puppet by default expects your command to finish running in 300 seconds or less. Then it gives up waiting and assumes the command failed.
I know nothing about pm2 to help you figure out why your command is taking so long. But if that's normal, then the link above suggests you add
timeout => 1800,
to your puppet definition.

I would recommend to manually find where the pm2 command is coming from ( $ which pm2 ) and then using the entire path of the command instead of using the path property. Something like this:
exec { "stop old application instance":
cwd => "${install_dir}",
onlyif => "test -e '${install_dir}/${app_package_dir}/processes.json'",
user => 'root',
command => "/usr/bin/pm2 delete /var/lib/application_folder/processes.json",
logoutput => 'onfailure',
}
Notice the logoutput property to see the output of the command only in case something breaks. I don't think you need to specify the group

You can try to put below in your puppet global script file :
Exec {
timeout => 0,
}

Related

Puppet exec/wget

I am trying to download a file from remote location into a directory in puppet.
.pp file
class test::test {
exec { 'wget http://10.0.0.1/test/test.txt':
cwd => '/opt/check',
path => ['/usr/bin', '/usr/sbin',],
}
}
I also tried with wget module in puppet :
class test::test {
include ::wget
wget::fetch { 'http://10.0.0.1/test/test.txt':
destination => '/tmp/',
timeout => 0,
verbose => false,
}
}
I am not getting the file downloaded, is there something i am doing wrong or is there a better way?
Please let me know.
Run which wget on your node to ensure you are including the right path, on my centos machine it's /bin/wget.
I often (and it's probably a bad habit) include the full path in the comand so I'd put /bin/wget http://10.0.0.1/test/test.txt
Have you tried running that command on the machine manualy?
Check this link out https://puppet.com/docs/puppet/5.5/type.html#exec
exec { 'get-test.txt':
cwd => '/opt/check',
command => '/bin/wget http://10.0.0.1/test/test.txt',
path => ['/usr/bin', '/usr/sbin',],
creates => '/opt/check/test.txt',
}
The "creates" stops running the exec if the file exists, you want to do that or every time puppet runs (default every 30 minutes) it'll run that command again.
I just ran a test on my machine, I created a file test.pp and put this in it;
exec { 'get-google':
cwd => '/tmp',
command => '/bin/wget http://www.google.com',
path => ['/usr/bin', '/usr/sbin',],
creates => '/tmp/index.html',
}
Then ran puppet apply test.ppand it worked, if you want to test small blocks of code that's a handy way of doing it.
Also, does the /opt/check directory exist?

Puppet exec a command before the package is installed

I am trying to run a power shell script just before the Pacakage starts installing an msi installer. The script cleans up certain un-managed resources that would block installer.
What I tried is,
file { 'c:\Test\cleanup.ps1.file' :
path => 'c:\Test\cleanup.ps1',
ensure => present,
source => 'puppet:///modules/test/cleanup.ps1',
source_permissions => ignore,
}
exec { 'c:\Test\cleanup.ps1.file':
refreshonly => true,
provider => powershell,
}
package { 'ServiceInstaller':
ensure => $version,
require => [Package['Service1Installer'],Exec['c:\Test\cleanup.ps1']],
}
But require attribute doesn't fire the command. Could someone please help me to achieve this behaviour.
There is this notify command, that would send a EXEC notification, but that happens after the installation. What I need is before the installation. Thanks in advance.
The trick to getting this working properly is that something has to write c:\Test\cleanup.ps1.file only when you need the script to be triggered to run, and the exec resource has to subscribe to it. Otherwise, if that file doesn't change, and the exec isn't subscribed, the exec resource does not think it needs to run so the puppet run completes but the script never fires.
Based on the code you pasted here, it looks like you're specifying $version in the class? And I'm guessing you're updating this either in the class or in hiera explicitly when you want to upgrade? If so, you could have the c:\Test\cleanup.ps1.file file write an inline template and just put the version number in that file. When you update the version in the class/hiera/wherever in puppet you're doing this, the file would update and the exec would kick off.
This would look something like:
file { 'c:\Test\cleanup.ps1.file' :
path => 'c:\Test\cleanup.ps1',
ensure => present,
content => inline_template("<%= #version %>"),
source_permissions => ignore,
}
exec { 'c:\Test\cleanup.ps1.file':
refreshonly => true,
provider => powershell,
subscribe => File['c:\Test\cleanup.ps1.file'],
}
package { 'ServiceInstaller':
ensure => $version,
require => [Package['Service1Installer'],Exec['c:\Test\cleanup.ps1']],
}
This is assuming you were just trying to use the cleanup.ps1.file as a trigger for the exec. If there is stuff in that file you need for other purposes, then leave that declaration as you had it, and make another file declaration as a trigger file with just the version in an inline template, and subscribe the exec to that one instead of the cleanup.ps1.file

Exec command time out Error when running nodejs app using puppet

I am cloning my repo and running my nodejs application using puppet. please find the code below:
package { 'git':
ensure => 'latest',
}
vcsrepo { "/nodejs-helloworld":
ensure => latest,
provider => git,
require => [ Package["git"] ],
source => "git#gitlab.abc.dev.net:hello-world/nodejs-helloworld.git",
revision => 'master',
before => Exec['/usr/local/bin/npm install;/usr/local/bin/npm start'],
}
exec { '/usr/local/bin/npm install;/usr/local/bin/npm start':
cwd => '/nodejs-helloworld',
subscribe => Vcsrepo['/nodejs-helloworld'],
refreshonly => true,
}
My repository is cloned, my application is running fine, and npm test also works. Everything works fine. However, I get an exec command time out error.
Error log:
[root#ip-*******/]# puppet agent -t
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Caching catalog for ip-**************
Info: Applying configuration version '1474433486'
Notice: /Stage[main]/Main/Exec[install-node-version-manager-global]/returns: executed successfully
Notice: /Stage[main]/Main/Exec[install-node-version-manager-latest]/returns: executed successfully
Notice: /Stage[main]/Main/Vcsrepo[/nodejs-helloworld]/ensure: Creating repository from latest
Notice: /Stage[main]/Main/Vcsrepo[/nodejs-helloworld]/ensure: created
Info: /Stage[main]/Main/Vcsrepo[/nodejs-helloworld]: Scheduling refresh of Exec[/usr/local/bin/npm install;/usr/local/bin/npm start]
Error: /Stage[main]/Main/Exec[/usr/local/bin/npm install;/usr/local/bin/npm start]: Failed to call refresh: Command exceeded timeout
Error: /Stage[main]/Main/Exec[/usr/local/bin/npm install;/usr/local/bin/npm start]: Command exceeded timeout
Notice: Finished catalog run in 302.86 seconds
As you can see here, even though I get an exec command timeout error, my app is running and npm test works.
[root#ip-********* nodejs-helloworld]# netstat -anp 2> /dev/null | grep :3000
tcp6 0 0 :::3000 :::* LISTEN 17630/node
[root#ip-********* nodejs-helloworld]# npm test
> nodejs-helloworld#1.0.0 test /nodejs-helloworld
> mocha
Test HelloWorld
✓ Should have the root route (46ms)
✓ Should have a hello world response
2 passing (66ms)
Can anyone please tell me how to avoid the exec command timeout error?
If I'm not wrong what seems to be the problem is that, when you run npm start, it runs your application but it doesn't exit, and you don't want that because you want to keep your application running, however puppet expects it to exit at some point.
What you should do instead is to make the exec resource start your application in the background. You can have a look at this question where the answers describe various tools to easily achieve this.

Puppet refuses to unzip archive

I want to download several libraries (guzzle, pimple) and unzip them immediately after.
For guzzle it works without any problems, however it refuses to unzip pimple and returns following error:
Exec[unflate-pimple]/returns: change from notrun to 0 failed: tar
-zvxf pimple-v1.1.1-0.tar.gz returned 2 instead of one of [0]
My exec:
exec {
"unflate-$lib_name":
cwd => "/var/www/lib/$lib_name",
command => "tar -zvxf $lib_name-$lib_version_prefix$lib_version.tar.gz",
path => "/usr/bin:/usr/sbin:/bin",
require => Exec["download-$lib_name"]
}
Where
$lib_name = "pimple"
$lib_version_prefix = "v"
$lib_version = "1.1.1-0"
Unzipping it manually in the terminal when connecting through SSH works fine.
I already tried unzipping and zipping it again.
I feel completely lost, where is the problem?
To debug this kind of misbehavior, add the logoutput => true parameter to the exec resource.
exec {
"unflate-$lib_name":
cwd => "/var/www/lib/$lib_name",
command => "tar -zvxf $lib_name-$lib_version_prefix$lib_version.tar.gz",
path => "/usr/bin:/usr/sbin:/bin",
require => Exec["download-$lib_name"],
logoutput => true,
}
Newer versions of Puppet default to on_error, which would be fine for your case, too.
The agent will then add the output of tar to the log. I cannot debug this for you further without seeing that output, but I suspect you will be able to solve the issue on your own once you see it.

Vagrant puppet change owner of folder in pp exec

I am trying to develop a CakePHP application, and I am using Vagrant to run a testing environment. However, I was getting this error in the browser
Warning (2):
session_start() [http://php.net/function.session-start]:
open(/var/lib/php/session/sess_speva7ghaftl8n98r9id5a7434, O_RDWR) failed:
Permission denied (13) [CORE/Cake/Model/Datasource/CakeSession.php, line 614]
I can get rid of the error by SSHing to the vm and doing
[vagrant#myserver ~]$ sudo su -
[root#myserver ~]# chown -R vagrant. /var/lib/php/session/
I don't want to have to do this every time I restart the vm, so I tried adding this to myserver.pp
exec { 'chown':
command => 'chown -R vagrant. /var/lib/php/session/',
path => '/bin',
user => 'root'
}
but it gets an error while starting up the vm...
err:
/Stage[main]/Myserver/Exec[chown]/returns: change from notrun to 0 failed:
chown -R vagrant. /var/lib/php/session/
returned 1 instead of one of [0] at /tmp/vagrant-puppet/manifests/myserver.pp:35
I was unable to find any useful examples of how to use exec on the internet, and I have never used Vagrant or Puppet before, so the above code is just the best guess I could come up with, and I apologize if it is a simple fix to get this working.
I have verified using which chown within the vm that the path is /bin, and the command is exactly the same as when I run it in the vm myself. I'm thinking it is the user that is causing problem. Do I have that line right? Is it even possible to exec commands as root from a .pp file?
When using exec, you normally have to enter the full path to the command you execute. So if you change your command into
exec { 'chown':
command => '/bin/chown -R vagrant:vagrant /var/lib/php/session/',
path => '/bin',
user => 'root'
}
it should work imo.
However, it depends a lot how you install your application. If the setup/start of the application is also managed with Puppet, you can also manage the directory you're interested in with Puppet, like this
file { "/var/lib/php/session" :
ensure => directory,
group => "vagrant",
owner => "vagrant",
recurse => true,
}
before you start your app. This would be much more the Puppet way, as you manage a reource then instead of executing commands. However, normally /var/lib/... should not be owned by someone other than root.
So you should maybe look into how your app is started and make it start with another user or as root. If it is started with an exec, you can add an additional property
user => root
to it and that should also do the trick.

Resources