I want to print out messages and variables when Puppet runs.
I saw there are two functions that might help but couldn't really use them.
My site.pp file:
info "running site.pp info"
debug "running site.pp debug"
When I run on the client:
puppet -t
I don't get those prints.
Here is the puppet script with all the available puppet log functions.
log_levels.pp
node default {
notice("try to run this script with -v and -d to see difference between log levels")
notice("function documentation is available here: http://docs.puppetlabs.com/references/latest/function.html")
notice("--------------------------------------------------------------------------")
debug("this is debug. visible only with -d or --debug")
info("this is info. visible only with -v or --verbose or -d or --debug")
alert("this is alert. always visible")
crit("this is crit. always visible")
emerg("this is emerg. always visible")
err("this is err. always visible")
warning("and this is warning. always visible")
notice("this is notice. always visible")
#fail will break execution
fail("this is fail. always visible. fail will break execution process")
}
Script output (on puppet 2.7):
NB: puppet 3.x colours may alter (all the errors will be printed in red)!
from the Puppet function documentation
info: Log a message on the server at level info.
debug: Log a message on the server at level debug.
You have to look a your puppetmaster logfile to find your info/debug messages.
You may use
notify{"The value is: ${yourvar}": }
to produce some output to your puppet client
If you want to notify user with different type of messages like information, debug, error, warning, alerts, critical and emergency messages then use ‘loglevel’ metaparameter in puppet resources.
With the use of loglevel you can use the same resources for different type of error messages.
e.g for producing debug messages you can use it as,
notify {"debug message":
loglevel => debug,
}
Just as alternative you may consider using execs... (I wouldn't recommend it though)
exec { 'this will output stuff':
path => '/bin',
command => 'echo Hello World!',
logoutput => true,
}
So when you run puppet you should find some output like so:
notice: /Stage[main]//Exec[this will output stuff]/returns: Hello World!
notice: /Stage[main]//Exec[this will output stuff]/returns: executed successfully
notice: Finished catalog run in 0.08 seconds
The first line being logged output.
You can run the client like this ...
puppet agent --test --debug --noop
with that command you get all the output you can get.
excerpt puppet agent help
* --test:
Enable the most common options used for testing. These are 'onetime',
'verbose', 'ignorecache', 'no-daemonize', 'no-usecacheonfailure',
'detailed-exitcodes', 'no-splay', and 'show_diff'.
NOTE: No need to include --verbose when you use the --test|-t switch, it implies the --verbose as well.
That does the task for me. I use that to check vars and display notifications..
notify {"hello world $var1":}
Here's the documentation on Puppet website as well: http://docs.puppetlabs.com/learning/ordering.html#notify-and-subscribe
Easier way, use notice.
e.g
notice("foo.pp works")
or
notice($foo)
If, like me, you don't have access to the puppet master and need to print debug logs to inspect variables on your puppet client machine, you can try writing to a file from your puppet code itself:
file { '/tmp/puppet_debug.log':
content => inline_template('<%= #variable_x.to_s %>'),
}
Have you tried what is on the sample. I am new to this but here is the command: puppet --test --trace --debug. I hope this helps.
You could go a step further and break into the puppet code using a breakpoint.
http://logicminds.github.io/blog/2017/04/25/break-into-your-puppet-code/
This would only work with puppet apply or using a rspec test. Or you can manually type your code into the debugger console. Note: puppet still needs to know where your module code is at if you haven't set already.
gem install puppet puppet-debugger
puppet module install nwops/debug
cat > test.pp <<'EOF'
$var1 = 'test'
debug::break()
EOF
Should show something like.
puppet apply test.pp
From file: test.pp
1: $var1 = 'test'
2: # add 'debug::break()' where you want to stop in your code
=> 3: debug::break()
1:>> $var1
=> "test"
2:>>
https://www.puppet-debugger.com
Related
I am trying to use Hammer in Foreman 1.20.1 on Centos 7.6 to refresh proxy features (or just about any other command other than --version) in a Puppet exec. The command I am using works fine at the shell. It fails in Puppet exec with:
Error: undefined local variable or method `dotfile' for
Notice: /Stage[main]/Profiles::Test/Exec[test]/returns: Did you mean?
##dotfile Notice: /Stage[main]/Profiles::Test/Exec[test]/returns:
Error: No such sub-command 'proxy'.
The code I am using is:
class profiles::test{
exec {'test':
command => '/usr/bin/hammer proxy refresh-features --name $(hostname)',
}
}
include profiles::test
I'm not concerned about idempotency as it will have a refreshonly, I just want to get the command to work.
I have tried adding other options such as path, user, environment etc to no avail. Any help appreciated.
from clues I found at https://github.com/awesome-print/awesome_print/issues/316 and https://grokbase.com/t/gg/puppet-users/141mrjg2bw/problems-with-onlyif-in-exec, it turns out that the HOME environment has to be set. So the working code is:
exec {'test':
command => '/usr/bin/hammer proxy refresh-features --name $(hostname)',
environment => ["HOME=/root"],
refreshonly => true,
}
f'ing ruby!
I'm reading that a shell command can be executed from custom facts with Facter::Core::Execution.exec. I've made a fact with the following code:
Facter.add(:controller_id) do
setcode do
Facter::Core::Execution.exec('/usr/bin/jq -r .device._id /var/lib/mylib/system.json')
end
end
When I run the command stand alone like /usr/bin/jq -r .device._id /var/lib/mylib/system.json on an agent it returns a string. But when I run the fact on my agent with puppet agent -t PuppetDb doesn't contain the new fact.
I can see that the agent sees the new fact code because it tells me my code has changed:
Notice:
/File[/opt/puppetlabs/puppet/cache/lib/facter/controller_id.rb]/content:
content changed '{md5}c3567db500497e3586617bfed072ca6d' to
'{md5}bb617198c5612eee365b5af8d410d4bc'
But no error is returned telling me why the fact wasn't saved. Does anyone know what might be causing this issue?
I wrote a simple module to install a package (BioPerl) on a Ubuntu VM. The whole init.pp file is here:
https://gist.github.com/anonymous/17b4c31bf7309aff14dfdcd378e44f40
The problem is it doesn't work, and it gives me no feedback to let me know why it doesn't work. There are 3 simple steps in the module. I checked and it didn't do any of them. Heres the first 2:
Step 1: Download an archive and save it to /usr/local/lib
exec { 'bioperl-download':
command => "sudo /usr/bin/wget --no-check-certificate -O ${archive_path} ${package_uri}",
require => Package['wget']
}
Step 2: Extract the archive
exec { 'bioperl-extract':
command => "sudo /usr/bin/tar zxvf ${archive_path} --directory ${install_path}; sudo rm ${archive_path}",
require => Exec['bioperl-download']
}
pretty simple. But I have no idea where the problem is because I can't see what its doing. The provisioner is set to verbose mode, and here are the output lines for my module:
==> default: Notice: /Stage[main]/Bioperl/Exec[bioperl-download]/returns: executed successfully
==> default: Notice: /Stage[main]/Bioperl/Exec[bioperl-extract]/returns: executed successfully
==> default: Notice: /Stage[main]/Bioperl/Exec[bioperl-path]/returns: executed successfully
So all I know is it executed these three steps successfully. It doesn't tell me anything about whether the steps did their job properly or not. I know that it didn't download the archive to /usr/local/lib that directory, and that it didn't add an environment variable file to /usr/profile.d. Maybe the issue is the variables containing the directories are wrong. Maybe the variable containing the archives download URI is wrong. How can I find these things out?
UPDATE:
It turns out the module does work. But to improve the module (since I want to upload it to forge.puppetlabs.com, I tried implementing the changes suggested by Matt. Heres the new code:
file { 'bioperl-download':
path => "${archive_path}",
source => "http://cpan.metacpan.org/authors/id/C/CJ/CJFIELDS/${archive_name}",
ensure => "present"
}
exec { 'bioperl-extract':
command => "sudo /bin/tar zxvf ${archive_name}",
cwd => "${bioperl_target_dir}",
require => File['bioperl-download']
}
A problem: It gives me an error telling me that the source cannot be http://. I see in the docs that they do indeed allow http:// files as the source for the file resource. Maybe I'm using an older version of puppet?
I want to try out the puppet-archive module, but I'm not sure how I can set it as a required dependency. By that, I mean how I can make sure its installed first. Do I need to get my module to download the module from github and save it to the modules directory? Or is there a way to let puppet install it automatically? I added it as a dependency to the metadata.json file, but that doesn't install it. I know I can just get my module to download the package, but I was wondering what best practice for this is.
The initial problem you describe is acceptance testing. Verifying that the Puppet resources and code you wrote actually resulted in the desired end state you wanted is normally accomplished with Serverspec: http://serverspec.org/. For example, you can write a Puppet module to deploy an application, but you only know that Puppet did what you told it to, and not that the application actually successfully deployed. Note Serverspec is also what people generally use to solve this problem for Ansible and Chef also.
You can write a Serverspec test similar to the following to help test your module's end state:
describe file('/usr/local/lib/bioperl.tar.gz') do
it { expect(subject).to be_file }
end
describe file('/usr/profile.d/env_file') do
it { expect_subject).to be_file }
its(:content) { is_expected.to match(/env stuff/) }
end
However, your problem also seems to deal with debugging why your acceptance tests failed. For that, you need unit testing. This is normally solved with RSpec-Puppet: http://rspec-puppet.com/. I would show you how to write some tests for your situation, but I don't think you should be writing your Puppet module the way that you did, so it would render the unit tests irrelevant.
Instead, consider using a file resource with the source attribute and a HTTP URI to grab the tarball instead of an exec with wget: https://docs.puppet.com/puppet/latest/type.html#file-attribute-source. Also, you might want to consider using the Puppet archive module to assist you: https://forge.puppet.com/puppet/archive.
If you have questions on how to use these tools to provide unit and acceptance testing, or have questions on how to refactor your module, then don't hesitate to write followup questions on StackOverflow and we can help you.
I'll need to add a apt repository key to a bunch of ubuntu hosts using puppet.
Would a statement like this work for that?
exec {"add apt key for elastic":
command => "/usr/bin/curl https://packages.elasticsearch.org/GPG-KEY-elasticsearch | /usr/bin/apt-key add -",
}
thanks
Yes, this should work but this will also apply the same configuration whenever you rerun Puppet.
From exec docs:
Any command in an exec resource must be able to run multiple times without causing harm — that is, it must be idempotent. There are three main ways for an exec to be idempotent:
The command itself is already idempotent. (For example, apt-get update.)
The exec has an onlyif, unless, or creates attribute, which prevents Puppet from running the command unless some condition is met.
The exec has refreshonly => true, which only allows Puppet to run the command when some other resource is changed. (See the notes on refreshing below.)
I try and only use execs if I really have to. One of the reasons being that you have to code the exec so that it only runs when you want to. Instead, you can use the apt module. This will only place the key on the host if it does not already exist. The resource is under puppet control so will not be added on subsequent runs:
include apt
apt::key { 'elasticsearch':
id => '46095ACC8548582C1A2699A9D27D666CD88E42B4',
options => 'https://packages.elasticsearch.org/GPG-KEY-elasticsearch',
}
I'm trying to restart my server with cron. I've found this link:
https://help.openshift.com/hc/en-us/articles/202187644-Shell-scripts-using-Cron-or-action-hooks-can-t-execute-shell-commands
But does not work. This is my script:
#!/bin/bash
source /usr/bin/rhcsh
ctl_all restart
And this the output:
/usr/bin/rhcsh: line 7: source: filename argument required
source: usage: source filename [arguments]
/usr/bin/rhcsh: line 32: build_path: command not found
/usr/bin/rhcsh: line 33: build_ld_library_path: No such file or directory
*********************************************************************
You are accessing a service that is for use only by authorized users.
If you do not have authorization, discontinue use at once.
Any use of the services is subject to the applicable terms of the
agreement which can be found at:
https://www.openshift.com/legal
*********************************************************************
Welcome to OpenShift shell
This shell will assist you in managing OpenShift applications.
!!! IMPORTANT !!! IMPORTANT !!! IMPORTANT !!!
Shell access is quite powerful and it is possible for you to
accidentally damage your application. Proceed with care!
If worse comes to worst, destroy your application with "rhc app delete"
and recreate it
!!! IMPORTANT !!! IMPORTANT !!! IMPORTANT !!!
Type "help" for more info.
Command "quota" not found for app xxxxx, please check the node hosting this app
WARNING: This ssh terminal was started without a tty.
It is highly recommended to login with: ssh -t
Restarting services
/usr/bin/rhcsh: line 123: gear: No such file or directory
Any ideas?
Many thanks.
Edit:
Here is rhcsh script (The script has 300 lines, so I've uploaded to a server):
http://www6.zippyshare.com/v/99209351/file.html
Try this:
#!/bin/bash
gear restart --all-cartridges # same as: ctl_all restart
ctl_all is a wrapper function for /usr/bin/gear script.