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}"],
],
}
Related
I am working a Puppet manifest that configures a router in the equipment that I support. The router runs pretty much plain vanilla Debian 8 or 9.
The problem is in the way the SSD on the router is partitioned.I am not able to change the partitioning, so have to work around the fact that the root file system is small. I have found a solution that I am trying to implement in Puppet but my first attempt doesn't feel right to me so I thought I would ask the community.
I have been and am reading the Puppet docs. Unfortunately I don't have my router hand to play with today so I am unable to test my current solution.
My issue is that by df -H the root file system is at 95% capacity and puppet is failing complaining about not enough space. Because of quirky decisions made a long time ago by others, the /opt/ file system is 5 times the size of / and is at 10% usage.
So my solution, tested manually, is to move /var/cache/apt/archives/ to /opt/apt-archives and then create a symlink using:
ln -s /opt/apt-archives /var/cache/apt/archives
That works and allows the puppet run to finish without errors.
My challenge is to implement this operation in a Puppet class
class bh::profiles::move_files {
$source_dir = '/var/cache/apt/archives'
$target_dir = '/opt/apt-cache'
file { $targetDir :
ensure => 'directory',
source => "file://${source_dir}",
recurse => true,
before => File[$source_dir]
}
file { $source_dir :
ensure => 'absent',
purge => true,
resurse => true,
force => true,
ensure => link,
target => "file://${target_dir}"
}
}
It just doesn't feel right to have ensure repeated in one file resource. And based on what I understand of creating links in puppet I would need the same name for the file resource that deletes the archives directory and the one that creates the link.
What am I missing?
Use exec:
exec { 'Link /var/cache/apt/archives':
command => 'mv /var/cache/apt/archives /opt/apt-archives
ln -s /opt/apt-archives /var/cache/apt/archives',
path => '/bin',
unless => 'test -L /var/cache/apt/archives',
}
Note that Puppet was not really designed to solve automation problems like this one, although using Exec it is possible to do most things anyway.
Your solution sounds like a work-around and it is therefore totally ok to implement a work-around using Exec. I would say, just make sure you add some comments explaining why you had to do something like this.
My puppet version is 2.7.25. What I would like to do is create a users home directory if it does not already exist and only if the user resides in LDAP.
I was hoping to use the exit status from this command to test upon.
/usr/bin/getent passwd username
Here is what I thought the puppet code would look like if I was running the correct version of puppet.
define ldap-users::virtual ($gid,$gname) {
$home_root = "/export/home"
file {
"${home_root}/${title}":
ensure => directory,
owner => $title,
group => $gid,
mode => 0700,
validate_cmd => "/usr/bin/getent passwd ${title}",
}
}
Using Felix's answer from validate_cmd in Puppet: supporting older versions, if you have puppetlabs-stdlib installed, you should be able to write some code that can do that for you. Something like this (might need modifying):
file {"${home_root}/${title}":
ensure => directory,
owner => $title,
group => $gid,
mode => '0700',
}
if versioncmp($puppetversion, '3.5') >= 0 {
File["${home_root}/${title}"] { validate_cmd => "/usr/bin/getent passwd ${title} #%"
}
else {
validate_cmd('/dev/null', '/usr/bin/getent passwd ${title} #%', "getent could not find the user specified ${title}")
}
This allows you to write backwards compatible code, that will still work when you upgrade beyond 3.5 (Which I would recommend, Puppet 2.7 has been EOL since October 1st 2013!)
Caveats
The validate_cmd is primarily used to point to a created file to run the command (such as visudo to check a sudoers file). So we can just make the validate_cmd run the getent command, and add a hash to comment out the actual file path.
Bear in mind this is not the standard usecase for the command, and will throw an error if the command fails, you might get some unexpected behaviour.
If you want a better workflow, a custom fact to check if the user exists before trying to create the folder might be a better idea:
require 'pathname'
export_home_dirs = Pathname.glob('/export/home/**')
export_home_dirs.each do |export_home|
Facter.add("export_home_user_#{export_home}") { setcode { "/export/home/#{export_home}" } }
end
Then gate your logic behind that custom fact.
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"]
}
}
First, I'm a newbie about Puppet (Configuration Management Tool).
-- And Please consider my poor English...
I got the order from my boss.
"Use Puppet, change the inner file of app.war"
The file is a property file that should be changed for each app server.
(but included in app.war ; it's a constraint.)
The workflow is like this (short description).
GOCD makes the app.war (conf.properties already included)
Our custom tool delivers this app.war to nodes.
At each node, Puppet runs the scripts below (not real, just a naive example).
-=-=-
exec { 'unzip':
command => 'gzip -d /temp/puppet/app.war',
path => '...',
}
exec { 'changefile':
command => 'cp /temp/puppet/conf.properties /temp/puppet/app/conf/conf.properties',
path => '...',
subscribe => Exec['unzip'],
}
exec { 'zip':
command => 'gzip /temp/puppet/app/ /temp/puppet/app.war',
path => '...',
subscribe => Exec['changefile'],
}
-=-=-
I just want to know about that this is a normal (or right or non-problematic) way to solve my situation.
Hmm... I think that Configuration Tools like Puppet are not suitable for this Application Deployment situation. (Though I'm a novice about CM.)
I tried to insist to use Rundeck, but I had no power (knowledge or executive).
Could you give me comments about this?
Thank you for all kind of comment...
I am using following script part to unzip my zip file. But the problem is it unzips the file always into a readonly folder. How can this be fixed.
exec { "install appliction server to pc":
command => 'unzip wso2as-5.2.1.zip',
cwd => '/home/malintha/adikari3/',
path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
logoutput => true,
timeout => 3600,
require => File['/home/malintha/adikari3/wso2as-5.2.1.zip'],
}
There are three parameters to the exec type, of which you should use at least one, to control when and when not to run
onlyif
unless
creates
The unzipping of an archive typically lends itself to a creates solution
exec { "unzip-file":
cwd => "/path/for/extraction",
creates => "/path/for/extraction/software-x.y",
...
}
assuming that the zip extracts into a directory tree rooted at software-x.y.
For more details, see the reference documentation.