I'm looking to make the following code work somehow, it seems if i do not test the files/folders first I end up with the error:
Error: Failed to apply catalog: Parameter path failed on
File[/opt/dynatrace-6.2]: File paths must be fully qualified, not
'["/opt/dynatrace-6.2", "/opt/dynatrace-5.6.0",
"/opt/rh/httpd24/root/etc/httpd/conf.d/dtload.conf",
"/opt/rh/httpd24/root/etc/httpd/conf.d/01_dtagent.conf"]' at
newrelic.pp:35
The pertinent parts
$dtdeps = [
"/opt/dynatrace-6.2",
"/opt/dynatrace-5.6.0",
"${httpd_root}/conf.d/dtload.conf",
"${httpd_root}/conf.d/01_dtagent.conf",
]
exec { "check_presence":
require => File[$dtdeps],
command => '/bin/true',
onlyif => "/usr/bin/test -e $dtdeps",
}
file { $dtdeps:
require => Exec["check_presence"],
path => $dtdeps,
ensure => absent,
recurse => true,
purge => true,
force => true,
} ## this is line 35 btw
exec { "stop_dt_agent":
command => "PID=$(ps ax |grep dtwsagent |grep -v grep |awk '{print$1}') ; [ ! -z $PID ] && kill -9 $PID",
provider => shell,
}
service { "httpd_restart" :
ensure => running,
enable => true,
restart => "/usr/sbin/apachectl configtest && /etc/init.d/httpd reload",
subscribe => Package["httpd"],
}
Your code looks basically correct, but you went overboard with your file resources:
file { $dtdeps:
require => Exec["check_presence"],
path => $dtdeps,
...
This does create all the file resources from your array (since you use an array for the resource title) but each single one of them will then try to use the same array as the path value, which does not make sense.
TL;DR remove the path parameter and it should Just Work.
You can actually simplify this down a lot. Puppet only runs the file removal if the files don't exist, so the check_presence exec is not required.
You can't give a path an array, but you can pass the title as an array and then the paths get automatically made.
$dtdeps = [
"/opt/dynatrace-6.2",
"/opt/dynatrace-5.6.0",
"${httpd_root}/conf.d/dtload.conf",
"${httpd_root}/conf.d/01_dtagent.conf",
]
file { $dtdeps:
ensure => absent,
recurse => true,
purge => true,
force => true,
}
exec { "stop_dt_agent":
command => '[ ! -z $PID ] && kill -9 $PID',
environment => ["PID=\$(ps ax |grep dtwsagent |grep -v grep |awk '{print$1}'))"],
provider => shell,
}
However, running the stop_dt_agent exec is a bit fragile. You could probably refactor this into a service resource instead:
service { 'dynatrace':
ensure => stopped,
provider => 'base',
stop => 'kill -TERM $(ps ax | grep \"dtwsagent\"|grep -v grep|awk '{print \$1}')',
status => "ps ax | grep "dtwsagent"",
}
Related
I was wondering if there is any way that i can remove my cron which got created through puppet. It works fine when i add "ensure => absent" to my manifest. But the challenge for me is, I have to wait an hour to run my puppet agent on my clients since agent is configured to run on every hour. Also i have to manually edit each job to add "ensure => absent".
Is there any other way that i can remove the cron than adding `"ensure => absent"` to each cron jobs
for example, how can we remove "job1" from all applied servers without adding "ensure => absent"
class cron::my_cron
(
)
{
cron::hourly { 'Job1':
minute => '0',
user => 'root',
command => 'cmd',
environment => [ 'MAILTO=root', 'PATH="/usr/bin:/bin"', ],
}
cron::hourly { 'job2':
minute => '0,5,10,15,20,25,30,35,40,45,50,55',
user => 'root',
command => 'cmd',
environment => [ 'MAILTO=root', 'PATH="/usr/bin:/bin"', ],
}
}
Here is the work around I found.
On my puppet class I have created an array with all my active crons. Then I will pass those list to my bash script. My bash script will install and execute once puppet agent run on my clients.
On my bash script i will grep for all my crons which installed via puppet then i loop through each cron job and compare with my active cron array, If it does not match with my active cron list, will execute the rm command to remove the cron entry.
class cron (
$active_cron=['cron1', 'cron2', 'cron3', 'cron4')
)
{
file {
'/usr/sbin/remove_cron.sh':
ensure => present,
mode => 755,
owner => 'root',
group => 'root',
content => template('cron/remove_cron.erb'),
notify => Exec['remove_cron'],
}
exec { 'remove_cron':
command => "/usr/sbin/remove_cron.sh >> /var/log/remove_cron.log",
path => '/usr/local/bin/:/bin/:/usr/bin/',
require => File['/usr/sbin/remove_cron.sh'],
refreshonly => true,
}
}
My Bash script template
#!/bin/bash
LIST='<%= #active %>'
grep -il puppet* /etc/cron.d/* | grep -il puppet* /etc/cron.d/* | awk -F"/" '{print $NF}' |while read CRON
do
FOUNDIT=$(echo $LIST |grep "\"$CRON\"" |wc -l)
if [ $FOUNDIT -eq 0 ]
then
echo "$(date) : Cron $CRON Removed"
rm -r /etc/cron.d/$CRON
fi
done
You don't have to wait for 30 minutes for the agents to run
Do "mco runall 5" on the puppetmaster to provoke a puppet agent run on all hosts
Then you can use "ensure => absent" and not have to bother with an exec hack
I am new to puppet and I have two questions. I want to execute 2 successive custom bash scripts:
file{ 'deploy_0':
ensure => 'file',
path => '/home/user_name/scripts/deploy_0.sh',
...
notify => Exec['deploy_core']
}
file{ 'deploy_1':
ensure => 'file',
path => '/home/user_name/scripts/deploy_1.sh',
...
notify => Exec['deploy_core_api']
}
exec { 'deploy_core':
command => '/bin/bash -c "/home/user_name/scripts/deploy_0"',
}
exec { 'deploy_core_api':
command => '/bin/bash -c "/home/user_name/scripts/deploy_1.sh"',
onlyif => 'deploy_core'
}
But this does not work
I know I can put for the onlyif paramter a bash command such as /bin/bash -c "/home/user_name/scripts/deploy_0.sh, but I prefer to declare a file resource.
You used the notify metaparameters correctly and well to specify the scripts needed to be deployed before execution (file before corresponding exec) and should be executed again if the file content changes. You need similar metaparameters for application order on the exec resources if you want similar functionality there. Note that onlyif is an exec attribute that executes a local command on the client and causes the resource to be considered already in sync (not applied due to idempotence) during catalog application if it returns something falsey.
Since you do not need refreshing here from one exec to the other like you did with the file resource, we can use require or before instead.
# before
exec { 'deploy_core':
command => '/bin/bash -c "/home/user_name/scripts/deploy_0"',
before => File['deploy_core_api'],
}
exec { 'deploy_core_api':
command => '/bin/bash -c "/home/user_name/scripts/deploy_1.sh"',
}
# require
exec { 'deploy_core':
command => '/bin/bash -c "/home/user_name/scripts/deploy_0"',
}
exec { 'deploy_core_api':
command => '/bin/bash -c "/home/user_name/scripts/deploy_1.sh"',
require => File['deploy_core'],
}
This will give you the behavior you are looking for.
I am trying to write a puppet script which will install a module by un-tar. I want puppet to fail if it is already un tar. I tried to do below code but it always fails even if directory is absent.
I am checking if /opt/sk is present then fail otherwise proceed on installation.
define splunk::fail($target)
{
$no = 'true'
case $no {
default : { notice($no) }#fail('sk is already installed.')}
}
}
define splunk::forwarder( $filename , $target )
{
file{"$target/sk":
ensure => present
}
splunk::fail{"NO":
target => '/opt/',
require => File[$target],
}
file{"$target/A.tgz":
source => $filename ,
replace => false ,
}
exec{"NO1":
command => "tar xzvf A.tgz" ,
cwd => $target ,
require => File["$target/A.tgz"] ,
}
exec{"Clean":
command => "rm -rf A.tgz" ,
cwd => target ,
require => Exec["NO1"],
}
}
splunk::forwarder {"non":
filename => 'puppet:///modules/splunk/files/NO.tgz' ,
target => '/opt/',
}
Thanks
Define custom_fact and use it combined with fail resource.
In your ruby directory e.g /usr/lib/ruby/vendor_ruby/facter define file tmp_exist.rb with content:
# tmp_exist.rb
Facter.add('tmp_exist') do
setcode do
File.exist? '/root/tmp'
end
end
Next use it in puppet manifest. E.g I combined it with str2bool function from stdlib:
class test {
if !str2bool($::tmp_exist) {
fail('TMP NOT EXIST')
}
if !str2bool($::foo_exist) {
fail('FOO NOT EXIST')
}
}
include test
In /root create only tmp file.
In result you will have:
Error: FOO NOT EXIST at /etc/puppet/deploy/tests/test.pp:8 on node dbmaster
UPDATED: I updated my answer. Chris Pitman was right, my previous solution works only on puppet master or with puppet apply.
I have also found an article describing how to define custom function file_exists in puppet. That also might be helpful.
You should use "creates" attribute of exec, for example:
exec { 'install':
command => "tar zxf ${package}",
cwd => $some_location,
path => $path,
creates => "${some_location}/my_package",
}
Puppet will only execute 'install' if "${some_location}/my_package" doesn't exist.
how can I configure a Exec to run only if another Exec ran?
I have a manifest like this:
file { $target:
ensure => directory
}
exec { "unzip foobar.zip -C ${target}":
unless => "file ${target}/some-file-form-archive"
}
exec { "chown -R $user ${target}":
onlyif => ???
}
I would like the chown to run only if unzip foobar.zip ran. Of course I could start checking whether some-file-from-archive is already owned by $user, but somehow it does not seem right.
There's an answer here already: http://ask.puppetlabs.com/question/14726/run-exec-only-if-another-exec-ran/
Changing the manifest like this fixes my problem:
exec { 'unpack file':
command => "unzip foobar.zip -C ${target}",
path => '/usr/bin',
creates => "${target}/some-file-form-archive",
require => File[$target, '<archive>'],
notify => Exec[fix archive],
}
exec { 'fix archive':
command => "chown -R ${user} ${target}",
path => '/bin',
refreshonly => true,
}
UPDATE 28.11.2014
motivated by Felix Frank's comment i tried out something else. instead of notify/refreshonly you can ensure all resource in a file-tree are owned by a user like this:
exec { 'fix archive':
command => "chown -R ${user} ${target}",
path => '/bin',
unless => "test 0 -eq $(find ${target} \\! -user ${user} | wc -l)"
}
this way owner is ensured to be $user even if it was changed after unpack file ran.
I have a sequence of exec in my Puppet manifest:
The first one downloads ZIP file with binary (unless the binary has already been installed) and saves it to /tmp.
The second one unzips it.
When I apply the manifest for the first time, it works correctly. However, when I clean my /tmp and apply the manifest again, it fails because the first exec doesn't executed (that is correct), but the second still tries to execute and fails because ZIP file is not present.
How do I modify the manifest to skip the second exec if the first one doesn't download file?
exec { 'ngrok-download':
command => 'wget https://dl.ngrok.com/linux_386/ngrok.zip -O /tmp/ngrok.zip',
unless => 'which ngrok',
path => ['/bin', '/usr/bin'],
}
exec { 'ngrok-unzip':
command => 'unzip ngrok.zip',
cwd => '/tmp',
path => ['/usr/bin'],
require => Exec['ngrok-download'],
}
Try this:
exec { 'ngrok-download':
command => 'wget https://dl.ngrok.com/linux_386/ngrok.zip -O /tmp/ngrok.zip',
unless => 'which ngrok',
path => ['/bin', '/usr/bin'],
notify => Exec['ngrok-unzip'],
}
exec { 'ngrok-unzip':
command => 'unzip ngrok.zip',
cwd => '/tmp',
path => ['/usr/bin'],
refreshonly => true,
require => Exec['ngrok-download'],
}
This will result in the unzip exec only running when the wget exec actually does something -- which it won't if ngrok is found.
Normally I would wget it to a more permanent location and leave it there. Then instead of the unless => 'which ngrok' check, replace with creates => '/path/to/zip.file'. The result being as long as the file is still there, none of the execs fire.
Comes in handy when you version the zip files and want to change versions.
You could also try easier approach:
exec { 'ngrok-download':
command => 'wget https://dl.ngrok.com/linux_386/ngrok.zip -O /tmp/ngrok.zip',
unless => 'which ngrok',
path => ['/bin', '/usr/bin'],
} ~>
exec { 'ngrok-unzip':
command => 'unzip ngrok.zip',
cwd => '/tmp',
path => ['/usr/bin'],
refreshonly => true,
}
Where Exec['ngrok-download'] notifies Exec['ngrok-unzip'] if applied and Exec['ngrok-unzip'] refresh its state only if needed
Same thing can be achieved by doing following:
exec { 'ngrok-download':
command => 'wget https://dl.ngrok.com/linux_386/ngrok.zip -O /tmp/ngrok.zip',
unless => 'which ngrok',
path => ['/bin', '/usr/bin'],
}
exec { 'ngrok-unzip':
command => 'unzip ngrok.zip',
cwd => '/tmp',
path => ['/usr/bin'],
refreshonly => true,
}
Exec['ngrok-download'] ~> Exec['ngrok-unzip']
Hope this helps.