Execute an Installer from the Puppet Filestore - puppet

I have stored the installer for a Linux product, which I need to install with an answer file. I have the following code thus far:
class installpackage {
file { 'MyInstallerFile':
path => '/tmp/MyInstallerFile',
ensure => present,
owner => 'root',
group => 'root',
mode => '777',
source => 'puppet:///extra_files/MyInstallerFile',
}
file { 'answer_file':
path => '/tmp/answer_file',
ensure => present,
owner => 'root',
group => 'root',
mode => '777',
source => 'puppet:///extra_file/answer_file',
}
exec { "install":
cwd => '/tmp',
command => '/tmp/MyInstallerFile --answer /tmp/answer_file',
logoutput => true,
require => File['MyInstallerFile', 'answer_file'],
}
}
However, when I attempt to run it, I get a bunch of errors:
Info: Retrieving plugin
Info: Loading facts in /var/lib/puppet/lib/facter/root_home.rb
Info: Loading facts in /var/lib/puppet/lib/facter/facter_dot_d.rb
Info: Loading facts in /var/lib/puppet/lib/facter/pe_version.rb
Info: Loading facts in /var/lib/puppet/lib/facter/puppet_vardir.rb
Info: Caching catalog for puppetagent.example.com
Info: Applying configuration version '1370899438'
Notice: /Stage[main]/Installpackage/Exec[install]/returns: couldn't find HOME environment variable to expand path
Notice: /Stage[main]/Installpackage/Exec[install]/returns: while executing
Notice: /Stage[main]/Installpackage/Exec[install]/returns: "file normalize ~"
Notice: /Stage[main]/Installpackage/Exec[install]/returns: (procedure "::InstallJammer::HomeDir" line 2)
Notice: /Stage[main]/Installpackage/Exec[install]/returns: invoked from within
Notice: /Stage[main]/Installpackage/Exec[install]/returns: "::InstallJammer::HomeDir"
Notice: /Stage[main]/Installpackage/Exec[install]/returns: (procedure "::InstallJammer::CommonInit" line 183)
Notice: /Stage[main]/Installpackage/Exec[install]/returns: invoked from within
Notice: /Stage[main]/Installpackage/Exec[install]/returns: "::InstallJammer::CommonInit"
Notice: /Stage[main]/Installpackage/Exec[install]/returns: (procedure "::InstallJammer::InitInstall" line 19)
Notice: /Stage[main]/Installpackage/Exec[install]/returns: invoked from within
Notice: /Stage[main]/Installpackage/Exec[install]/returns: "::InstallJammer::InitInstall"
Notice: /Stage[main]/Installpackage/Exec[install]/returns: (file "/installkitvfs/main.tcl" line 71313)
Error: /tmp/MyInstallerFile --answer /tmp/answer_file returned 1 instead of one of [0]
Error: /Stage[main]/Installpackage/Exec[install]/returns: change from notrun to 0 failed: MyInstallerFile --answer /tmp/answer_file returned 1 instead of one of [0]
Notice: Finished catalog run in 5.31 seconds
What about I doing wrong?

By default, Puppet runs as root user.
I think your $HOME environment variable is not set by root.
As a test, you may su to root, and echo $HOME to find out if that is the case.

Try explicitly setting the $HOME variable on the command line:
exec { "install":
...
command => 'HOME=/path/to/somewhere /tmp/MyInstallerFile --answer /tmp/answer_file',
...
}

The problem seemed to be the way the machines were imaged, and one solution to fix the Exec issues was to add "sudo" in front of the command. Of course, this is only limited to Linux environments.
The other solution, and probably a better idea is to create Debian packages of installers that you need. This simplifies management, and rolling out new versions rather than going through uninstall routines.

You gotta do something like this.
$path => $::path,
$cwd => '/location/of/your/installer'
$::path is a reference to the default environment variables.You can set additional path in an array like this.
$path => [$::path,'/additional/path/to/other/directory'],
$cwd => '/location/of/your/installer',

Related

Puppet Could not find command 'cd'

Hi there this part of my code causes an error.
path => '/bin:/sbin/:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin',
cwd => "/var/rapid7installer && unzip ${install_file}",
creates => '/var/rapid7installer/agent_installer.sh',
timeout => $timeout,
require => [
Package['unzip'],
File["/var/rapid7installer/${install_file}"],
],
}->
This is the error I am getting.
Error: /Stage[main]/Profiles::Rapid7agent/Exec[Rapid7 Agent Installation Unzip]/returns: change from 'notrun' to ['0'] failed: Could not find command 'cd'
I am hoping someone can help me or point me in the right direction. Thank you for looking and your time.
The fragment presented in the question is an incomplete unit, but it appears to be part of the declaration of an Exec resource. In that case, the cwd attribute is surely incorrect:
cwd => "/var/rapid7installer && unzip ${install_file}",
, and it probably is directly responsible for the issue you observe. The value of that attribute should be the name of a directory that should be the working directory during execution of the exec's command. From context, it appears that that should be just the first part, /var/rapid7installer. The actual command to execute must be conveyed via the command attribute, which defaults to the resource title if not given explicitly.
Thus, it appears you want something more like this:
exec { 'Rapid7 Agent Installation Unzip':
command => "unzip ${install_file}",
path => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin',
cwd => '/var/rapid7installer',
creates => '/var/rapid7installer/agent_installer.sh',
timeout => $timeout,
require => [
Package['unzip'],
File["/var/rapid7installer/${install_file}"],
],
}

puppet / facter: "created(corrective)"

I use puppet to update / maintain itself (among other things). For some reason every time the client runs I get these two actions:
Notice: /Stage[main]/Servers::Packages::Puppet/Package[facter]/ensure: created (corrective)
Notice: /Stage[main]/Servers::Packages::Puppet/Package[puppet]/ensure: created (corrective)
The definitions in question look like this:
package { 'puppet' :
ensure => 'latest',
require => Package['facter'];
}
package { 'facter' :
ensure => 'latest',
}
file { '/etc/default/puppet' :
ensure => 'file',
mode => '644',
source => 'puppet:///modules/servers/packages/puppet/default';
}
file{ '/etc/puppetlabs/puppet/puppet.conf' :
mode => '644',
content => template("servers/packages/puppet/puppet_conf.erb"),
require => Package[ 'puppet' ];
}
service{ 'puppet' :
ensure => 'running',
enable => true,
require => Package[ 'puppet' ],
subscribe => [
File[ '/etc/default/puppet'],
File[ '/etc/puppetlabs/puppet/puppet.conf'],
];
}
What's wrong with my definition(s)? Why do puppet / facter appear to be reinstalled with every run?
Since Puppet 4, Puppet, Inc. has provided only all-in-one packages of client-side components, not named either 'puppet' or 'facter'. The package for Puppet 6 is named puppet-agent -- this is what you should be managing, not packages named 'puppet' or 'facter'.
The messages you report indicate that Puppet does not see up-to-date 'puppet' or 'facter' packages, which is natural because these do not exist. They also indicate that puppet thinks it has corrected the problem -- which it will have attempted to do by installing / updating packages with those names, and which apparently succeeded. This seeming incongruity will have arisen because the puppet-agent packages declare that they provide features named "puppet" and "facter", which your package manager is using to associate those package names with the puppet-agent package. As a result, the installation / update succeeds without actually installing anything new, leaving the system primed to do the same thing over again on the next run.
I suspect that the "(corrective)" marks on the log output reflect package-manager exit statuses indicating success without doing anything.

Puppet: how to add a line to an existing file

I am trying to add a line to an existing file /etc/fuse.conf. I tried this
added a folder two folders under modules directory
sudo mkdir /etc/puppet/modules/test
sudo mkdir /etc/puppet/modules/test/manifests
Then created a test.pp file and added following lines
sudo vim /etc/puppet/modules/test/manifests/test.pp
file { '/etc/fuse.conf':
ensure => present,
}->
file_line { 'Append a line to /etc/fuse.conf':
path => '/etc/fuse.conf',
line => 'Want to add this line as a test',
}
After that I ran this command
puppet apply /etc/puppet/modules/test/manifests/test.pp
Then I opened this file /etc/fuse.conf and there was no change in the file. The line was not added to the file. I don't understand what I am missing here. How can I do this?
Interesting. I ran the same test you did without an issue, and as long as you have stdlib installed in your environment you should be fine.
https://forge.puppet.com/puppetlabs/stdlib
The results of running the same steps you outlined were successful for me:
[root#foreman-staging tmp]# puppet apply /etc/puppet/modules/test/manifests/test.pp
Notice: Compiled catalog for foreman-staging.kapsch.local in environment production in 0.18 seconds
Notice: /Stage[main]/Main/File[/etc/fuse.conf]/ensure: created
Notice: /Stage[main]/Main/File_line[Append a line to /etc/fuse.conf]/ensure: created
Notice: Finished catalog run in 0.24 seconds
What did your puppet run output?
You should use templates (ERB) to handle file configuration. Its easier and cleaner.
Check the puppet docs for it in :
https://docs.puppetlabs.com/puppet/latest/reference/lang_template.html
There are other options though. e.g. Augeas which is an API for file configuration and integrate very well with Puppet. http://augeas.net/index.html
[]'s
There are a few ways to handle this. If it's ini file you can use ini_setting. If it's supported by augeas you can use that. Otherwise try specifying the after parameter to file_line

Custom fact should run after a package is installed

I have a small custom fact in a my php module
Facter.add('php_extension_version') do
setcode do
Facter::Core::Execution.exec("php -i | awk '/^PHP Extension =>/ { print $4}'") || nil
end
end
This obviously requires the php binary to be installed. However, I noticed that all facts are run once before applying the catalog, so this fact is invalid before php installed.
Is there any way of gathering the information after the module is installed? Is there perhaps another way of exposing this information except facter?
Update
I'm using the two facts to determine which of multiple .so files is the right one to install:
if $php_zts_enabled {
$so_name = "newrelic-$php_extension_version.so"
} else {
$so_name = "newrelic-$php_extension_version-zts.so"
}
file {"/usr/lib64/php5/extensions/newrelic.so":
source => "file:///opt/newrelic-php5-$version-linux/agent/x64/$so_name",
owner => root,
group => root,
mode => 0644,
notify => Service['apache'],
require => Exec["extract-php-agent-$version"]
}
The files that are located in the agent/x64 directory can be
newrelic-20060613.so newrelic-20090626-zts.so newrelic-20121212.so newrelic-20131226-zts.so
newrelic-20060613-zts.so newrelic-20100525.so newrelic-20121212-zts.so
newrelic-20090626.so newrelic-20100525-zts.so newrelic-20131226.so
You essentially have only two opportunities to execute code on the node:
As part of a Facter fact. As you are aware, this happens before puppet applies a catalog, so any facts dependent on the results of the puppet run will not be useful until the next run.
As part of a custom provider. You can create a custom type and provider for installing the extensions that checks the node state before deciding what to do. Providers execute on the node, and as long as you know the overall provider lifecycle you can make this happen after the PHP install. However, this is incredibly complex compared to normal puppet modules.
Outside of those options, the normal way of doing this would be to enforce the version and configuration of php within your own manifests, and then pass that information to here. You should already know the version of PHP and its extensions based on what packages you have installed.
I would modify the fact so that it's present only when the binary is present (hence it won't be present at the very first run).
Facter.add('php_extension_version') do
setcode do
if system("which php > /dev/null 2>&1")
Facter::Core::Execution.exec("php -i | awk '/^PHP Extension =>/ { print $4}'") || nil
end
end
end
and then in your manifest you'd wrap the original code in the if
if $php_extension_version {
if $php_zts_enabled {
$so_name = "newrelic-$php_extension_version.so"
} else {
$so_name = "newrelic-$php_extension_version-zts.so"
}
file {"/usr/lib64/php5/extensions/newrelic.so":
source => "file:///opt/newrelic-php5-$version-linux/agent/x64/$so_name",
owner => root,
group => root,
mode => 0644,
notify => Service['apache'],
require => Exec["extract-php-agent-$version"]
}
}

Can't use augeas to create a new entry in hosts.allow

I try to create a new entry in hosts.allow
augeas { "Add in hosts allow" :
context => '/files/etc/hosts.allow',
changes => [
'ins 01 after *[last()]',
'set 01/process[1] ssh',
'set 01/process[2] ssh2',
'set 01/client ipaddr'
],
}
But it doesn't work I get this error
Notice: Compiled catalog for server.local in environment production in 0.96 seconds
Error: /Stage[main]/Nfs::Server/Augeas[Add in hosts allow]: Could not evaluate: Error sending
command 'ins' with params ["01", "after", "/files/etc/hosts.allow/*[last()]"]/Error sending
command 'ins' with params ["01", "after", "/files/etc/hosts.allow/*[last()]"]
I can't see how to use the ins command, the message don't let me know what's went wrong.
CentOS6.4
Puppet version: 3.3.1
augeasversion (from facter): 0.9.0
I Can't find the version of augtools and I can't either execute a command as it is not installed (I don't know how puppet invoke it)
Try adding a leading "/" to the context?
(The logging is slightly odd, it doesn't show the "files" prefix at all, I wonder if your code sample and logging match.)

Resources