I am new to puppet. I want to run a shell script call crfs.sh located under /myscripts on a RHEL linux puppet master server.
How do I execute this script on a client or target server?
What you want can be solved using the file and the exec modules of puppet.
class mymodule::myclass {
file { 'my_bash_script':
ensure => 'file',
source => 'puppet:///modules/mymodule/my_bash_script.sh',
path => '/usr/local/bin/my_bash_script.sh',
owner => 'root'
group => 'root'
mode => '0744', # Use 0700 if it is sensitive
notify => Exec['run_my_script'],
}
exec { 'run_my_script':
command => '/usr/local/bin/my_bash_script.sh',
refreshonly => true,
}
}
Related
I want to deploy certs in default keystore using puppet
I have two files root.crt and intermediateca.crt managed by puppet. I will have many alias and cert file in future
Alias could be rootca, intermediateca.This alias and filepath should be passed to exec command.
alias=rootca, intermediateca
filecert= "/var/lib/certs/rootca", "/var/lib/certs/intermediateca.crt"
Now I am running an exec command which takes alias and crt file as an argument in exec command resource.
'/var/lib/certs':
ensure => directory;
'/var/lib/certs/root.crt':
source => "puppet:///modules/${module_name}/sonarqube/${::env}/var/lib/certs/root.crt",
mode => '0644',
notify => Exec['markitrootca'];
'/var/lib/certs/intermediateca.crt':
source => "puppet:///modules/${module_name}/sonarqube/${::env}/var/lib/certs/intermediateca.crt",
mode => '0644',
notify => Exec['markitintermediateca'];
}
exec {
'markitrootca':
path => "/usr/bin",
command => "keytool -importcert -keystore ${keystore} -alias markitrootca -file /var/lib/certs/root.crt -storepass ${storepass} -noprompt 2>/dev/null",
provider => shell,
refreshonly => true;
'markitintermediateca':
path => "/usr/bin",
command => "keytool -importcert -keystore ${keystore} -alias markitintermediateca -file /var/lib/certs/intermediateca.crt/ -storepass ${storepass} -noprompt 2>/dev/null",
provider => shell,
refreshonly => true;
}
The above solution is working fine but I want to write only one exec for multiple alias and filepaths. How can i achieve that?
What it sounds like you are asking here is how to iterate over a hash and have each resource in the iteration notify an exec resource. Given that, you can use a lambda iterator on the hash. If this is not true, then please clarify the question with terminology and details. First you construct the hash with your keys:
$certs = { 'rootca' => '/var/lib/certs/rootca',
'intermediateca' => '/var/lib/certs/intermediateca.crt' }
Then you can iterate over the hash with the each method.
$certs.each |String $cert, String $loc| {
# code here
}
Populating the body of the lambda would look like this for your situation:
$certs.each |String $cert, String $loc| {
file { $loc:
source => "puppet:///modules/${module_name}/sonarqube/${::env}${loc}",
mode => '0644',
notify => Exec['install_cert'];
}
}
Note that in your question it looked like you were doing per-resource default attributes, but it is unclear since the rest of the body is missing, so I converted it to a conventional resource.
The entire body of code would look like:
$certs = { 'rootca' => '/var/lib/certs/rootca',
'intermediateca' => '/var/lib/certs/intermediateca.crt' }
$certs.each |String $cert, String $loc| {
file { $loc:
source => "puppet:///modules/${module_name}/sonarqube/${::env}${loc}",
mode => '0644',
notify => Exec['install_cert'];
}
}
exec { 'install_cert':
path => "/usr/bin",
command => "keytool -importcert -keystore ${keystore} -alias $alias -storepass ${storepass} -noprompt -trustcacerts",
provider => linux,
subscribe => File['/var/lib/certs/'],
refreshonly => true;
}
Since you did not mention in the question what keystore and storepass are, I will have to assume you are defining them elsewhere. Also you are subscribing to File['/var/lib/certs/'] which I also have to assume is somewhere else.
There are other improvements you can make here, including:
Not specifying the provider in the exec.
Not using the path in the exec since it is a string and not an array of search paths and instead providing the full path to keytool.
Not subscribing to File['/var/lib/certs/'] since the exec does not care about that directory and the notify are providing the necessary functionality.
Not specifying the path to the certs since they are always in the same location, so you can use a single array instead of a hash.
env looks like a fact and not a global variable, so it should be specified as such.
Not having a deep source for your file resources and instead just storing them inside the env directory.
Helpful documentation on lambda iterators can be found here.
There is a much better way to do this. you can simple define a hierayaml file with an array of objects/task or just write it directly in.
instead of code such as
# Run Start Script*
exec { 'run script':
command => "somecmdhere",
provider => shell,
cwd => 'dir',
refreshonly => false,
logoutput => true
}
exec { 'run installation script':
command => "${target_dir}/${start_service_script}",
provider => shell,
cwd => $target_dir,
refreshonly => false,
logoutput => $cmdlogoutput
}
you can use create resource with arguments TYPE and Objects to create
create_resources('package', )
in this case we would use
#goes and looks for yaml file with variable exec scripts. This can be done by also defining it in puppet.
$listofExecCommands = hiera_hash('execScripts::allscripts)
create_resources('exec', $listofExecCommands)
Then where ever you define your YAML file you can re-use it with no code changes.
you can use this for RPMS NPM packages its great! ps make sure your yaml is correct*
#RPM packages to be installed
execScripts::allscripts:
'script1':
command: 'installed'
provider: 'yum'
cwd: 'somedir'
'script2':
command: 'installed'
provider: 'yum'
cwd: 'somedir'
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 install a particular rpm using puppet, my init.pp is:
class nmap {
package {'nmap':
provider => 'rpm',
source => "<Local PATH to the RPM>",
}
}
and the rpm is in ...modules/nmap/files
If i move the rpm to manifests, and provide the rpm name in source => ''
class nmap {
package {'nmap':
provider => 'rpm',
source => "rpm-name.rpm",
}
}
it works, but how can i specify source path with ../files/ and do puppet apply successfully
When i use :
source => 'puppet:///files/nmap-6.45-1.x86_64.rpm',
i get an error:
Debug: Executing '/bin/rpm -i puppet:///files/nmap-6.45-1.x86_64.rpm'
Error: Execution of '/bin/rpm -i puppet:///files/nmap-6.45-1.x86_64.rpm' returned 1: error: open of puppet:///files/nmap-6.45-1.x86_64.rpm failed: No such file or directory
Error: /Stage[main]/Nmap/Package[nmap]/ensure: change from absent to present failed: Execution of '/bin/rpm -i puppet:///files/nmap-6.45-1.x86_64.rpm' returned 1: error: open of puppet:///files/nmap-6.45-1.x86_64.rpm failed: No such file or directory
`
when running the command:
sudo puppet apply --modulepath=/home/user1/qa/puppet_qa/modules/ -e "include nmap" --debug
Unlike the file resource type, the package type has no support for Puppet fileserver URLs. You will need to use a file resource to download the rpm prior to installing it. If this is a recurring problem for you, make a defined type that does those in one go (think macros), e.g.
define fileserver_package($source, $ensure='installed') {
file { "/my/tmp/dir/$name.rpm": source => $source }
package { $name:
ensure => $ensure,
provider => 'rpm',
source => "/my/tmp/dir/$name.rpm",
require => File["/my/tmp/dir/$name.rpm"],
}
}
Edit: it is generally advisable to use a local yum repo instead, see also the first comment by #rojs below.
The RPM package can be installed this way:
package { 'epel-release-6':
provider => 'rpm',
ensure => 'present',
source => '/usr/local/rpms/epel-release-latest-6.noarch.rpm',
}
It seems the module name you are using is nmap. You can use the same source parameter like this,
source => 'puppet:///modules/nmap/nmap-6.45-1.x86_64.rpm',
The syntax to access a file under a module goes like this,
puppet:///modules/<modulename>/<file you want to access>
See this link here, http://docs.puppetlabs.com/puppet/latest/reference/modules_fundamentals.html#files
Lets start from start :
on server:
$rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el-7.noarch.rpm
$yum -y install puppetserver
$vi /etc/sysconfig/puppetserver #change JAVA args
$systemctl start puppetserver
$systemctl enable puppetserver
$vi /etc/puppetlabs/puppet/puppet.conf #Add “dns_alt_names” in [master]
On Agent:
$rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el-7.noarch.rpm
$yum -y install puppet-agent
$systemctl start puppet
$systemctl enable puppet
$vi /etc/puppetlabs/puppet/puppet.conf # Add “server = pupmaster” in [main]
puppet cert list
puppet cert sign
/etc/puppetlabs/code/environments/production/manifests/site.pp:
node webserver {
class { 'apache': }
}
node dbserver {
class { ‘mysql’: }
}
mkdir –p /etc/puppetlabs/code/environments/production/modules/apache/{manifests, files}
apacheinstall.pp:
class apache::apacheinstall {
if $osfamily == 'redhat' {
package { 'httpd':
ensure => 'latest'
}
service {'httpd':
ensure => 'running',
require => Package["httpd"],
}
file { '/var/www/html/ndex.html':
mode => "0644",
owner => 'root',
group => 'root',
source => 'puppet:///modules/apache/index.html',
}
}
elsif $osfamily == 'debian' {
package { 'apache2':
ensure => 'latest'
}
service {'httpd':
ensure => 'running',
require => Package["httpd"],
}
}
}
INIT.pp
class apache {
notify { 'Installing and Configuring Webserver for $osfamily': }
include apache::mysqlinstall
}
Mysqlinstall.pp:
class apache::mysqlinstall {
exec { 'wget':
path => [ "/bin/", "/sbin/", "/usr/bin/", "/usr/sbin/" ],
command => "/usr/bin/wget https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm && rpm -ivh /tmp/mysql57-community-release-el7-9.noarch.rpm",
cwd => '/tmp/',
creates => '/etc/firstruns/p1.done',
}
}
A small puppet question
I am creating a composer project like so.
composer::project { 'project-test':
ensure => 'latest', #or installed?
target => '/home/test/www',
dev => false,
require => Package ['php', 'apache']
}
And then from an exec I want to require it as a resource. How can I?
Example of exec:
exec { 'generate-tests' :
command => 'php tests.php',
path => '/usr/bin/',
cwd => "/home/test/www/bin",
logoutput => 'true',
#require => composer::project['project-test']
}
Since what you're requiring is a resource, it should be capitalized as follows:
require => Composer::Project['project-test']
Hi guys am new to puppet and I want to execute the following command on client using puppet so that the fast cgi mod is enabled on the puppet client.
lighttpd-enable-mod fastcgi
Both puppet server and client are ubuntu machines and my lighttpd module's init.pp file is as follows:
class lighttpd::install {
package { "lighttpd":
ensure => present,
}
}
class lighttpd::conf {
file { "/etc/lighttpd/lighttpd.conf":
ensure => present,
owner => 'root',
group => 'root',
mode => 0600,
source => "puppet:///modules/lighttpd/lighttpd.conf",
require => Class["lighttpd::install"],
}
}
class lighttpd::fastcgi {
file { "/etc/lighttpd/conf-available/10-fastcgi.conf":
ensure => present,
owner => 'root',
group => 'root',
mode => 0600,
source => "puppet:///modules/lighttpd/10-fastcgi.conf",
require => Class["lighttpd::install"],
}
}
class lighttpd {
include lighttpd::install, lighttpd::conf, lighttpd::fastcgi
}
Please help me execute this command on the puppet client.
Thanks
So if you modify your lighttpd::fastcgi class to be something like:
class lighttpd::fastcgi {
file { "/etc/lighttpd/conf-available/10-fastcgi.conf":
ensure => present,
owner => 'root',
group => 'root',
mode => 0600,
source => "puppet:///modules/lighttpd/10-fastcgi.conf",
require => Class["lighttpd::install"],
notify => Exec["enable-mod-fastcgi"],
}
exec { "enable-mod-fastcgi":
command => "/usr/bin/lighttpd-enable-mod fastcgi",
refreshonly => true,
}
}
(sorry - the path may be wrong to lighttpd-enable-mod - I don't have lighttpd here).
This should notify the 'exec' correctly. The exec will only get called when notified because of the 'refreshonly' parameter being true.