Copy contents of symlink to directory - puppet

I am trying to copy the contents of a symlink directory to a normal directory on Windows:
file { "copy symlink contents to directory":
ensure => directory,
path => "C:/Users/devacct/Desktop/puppet/puppet_dir2/", #directory
source => "C:/Users/devacct/Desktop/puppet/filessym/", #symlink
recurse => true,
source_permissions => ignore,
links => 'manage',
#ignore => $ignore_files,
#purge => $purge,
force => true,
}
This fails with an error message:
Error: /Stage[main]/Custom::Profile::Symlink/File[copy symlink contents to directory]: Could not evaluate: Could not retrieve information from environment production source(s) file:/C:/Users/devacct/Desktop/puppet/filessym
Is it valid to give symlink path as a value to source attribute? If not, how do I achieve my objective?

Use the link attribute on your file block with follow.
Also, set the source without the last backslash... Give this a try.
file { "copy symlink contents to directory":
ensure => directory,
path => "C:/Users/devacct/Desktop/puppet/puppet_dir2/", #directory
source => "C:/Users/devacct/Desktop/puppet/filessym", #symlink
recurse => true,
source_permissions => ignore,
links => 'follow',
#ignore => $ignore_files,
#purge => $purge,
force => true,
}

Yes, it is valid in general to use a symlink as the source parameter, and as noted by Kelson Silva, you would also need to use links => follow instead of links => manage (see docs).
I am not sure why you are getting that error message though.
FWIW, I tested the following on Mac OS X:
Set up:
$ ls -ld /tmp/symlink
lrwxr-xr-x 1 alexharvey wheel 10 12 May 16:31 /tmp/symlink# -> realsource
$ ls -lL /tmp/symlink
total 0
drwxr-xr-x 5 alexharvey wheel 160 12 May 16:30 a/
drwxr-xr-x 5 alexharvey wheel 160 12 May 16:30 b/
drwxr-xr-x 5 alexharvey wheel 160 12 May 16:30 c/
$ find /tmp/symlink/
/tmp/symlink/
/tmp/symlink//a
/tmp/symlink//a/f
/tmp/symlink//a/d
/tmp/symlink//a/d/somefile
/tmp/symlink//a/e
/tmp/symlink//c
/tmp/symlink//c/f
/tmp/symlink//c/d
/tmp/symlink//c/e
/tmp/symlink//b
/tmp/symlink//b/f
/tmp/symlink//b/d
/tmp/symlink//b/e
Code:
file { '/tmp/dest':
ensure => directory,
links => follow,
source => '/tmp/symlink',
recurse => true,
source_permissions => ignore,
force => true,
}
Result:
Notice: Compiled catalog for harveya-c02vj38lhtd7-ume.local in environment production in 0.03 seconds
Notice: /Stage[main]/Test/File[/tmp/dest]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/a]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/a/d]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/a/d/somefile]/ensure: defined content as '{md5}d41d8cd98f00b204e9800998ecf8427e'
Notice: /Stage[main]/Test/File[/tmp/dest/a/e]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/a/f]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/b]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/b/d]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/b/e]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/b/f]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/c]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/c/d]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/c/e]/ensure: created
Notice: /Stage[main]/Test/File[/tmp/dest/c/f]/ensure: created
Notice: Applied catalog in 0.13 seconds

Related

how to ensure puppet exec run on every event triggered?

I want puppet exec to run on first deployment of a file and on every further change on the file. For that I have created below code in puppet .
Exec does not run on first file deployment. I am assuming it is because of refreshonly. Does anyone know what needs to be changed in the code?
define dev_tools::javacert(
$keystore="/etc/alternatives/java_sdk/jre/lib/security/cacerts",
$storepass='xxx',
$alias = $name,
$filecertpath = "/var/lib/certs/${name}.crt",
){
file{
$filecertpath:
source => "puppet:///modules/${module_name}/sonarqube/${::env}/${::server_location}/${filecertpath}",
mode => '0644',
notify => Exec["deploy_javacert_${name}"];
}
exec {
"deploy_javacert_${name}":
path => "/usr/bin",
command => "keytool -importcert -keystore ${keystore} -alias $alias -file $filecertpath -storepass ${storepass} -noprompt 2>/dev/null",
provider => shell,
refreshonly => true;
}
}
The use of refreshonly looks correct. I am unable to reproduce this. Using this simplified version of your code:
Attempt to create a MCVE:
# test.pp
file { 'foo':
path => '/tmp/foo',
source => '/tmp/source',
notify => Exec['bar'],
}
exec { 'bar':
path => '/bin',
command => 'echo "baz qux"',
refreshonly => true,
logoutput => true,
}
Setup:
▶ touch /tmp/source
Initial run:
▶ puppet apply test.pp
...
Notice: /Stage[main]/Main/File[foo]/content: content changed '{md5}0a227d644d5435d49addae1da06e909c' to '{md5}d41d8cd98f00b204e9800998ecf8427e'
Notice: /Stage[main]/Main/Exec[bar]/returns: baz qux
Notice: /Stage[main]/Main/Exec[bar]: Triggered 'refresh' from 1 event
Subsequent run:
▶ puppet apply test.pp
...
Notice: Compiled catalog for 192-168-1-2.tpgi.com.au in environment production in 0.08 seconds
Notice: Applied catalog in 0.03 seconds
New content:
▶ echo foobar > /tmp/source
▶ puppet apply test.pp
...
Notice: /Stage[main]/Main/File[foo]/content: content changed '{md5}d41d8cd98f00b204e9800998ecf8427e' to '{md5}14758f1afd44c09b7992073ccf00b43d'
Notice: /Stage[main]/Main/Exec[bar]/returns: baz qux

Puppet can't find class firewall

I have a basic puppet install using this tutorial https://www.digitalocean.com/community/tutorials/how-to-install-puppet-4-on-ubuntu-16-04
When I run /opt/puppetlabs/bin/puppet agent --test on my node I get
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Error while evaluating a Resource Statement. Could not find declared class firewall at /etc/puppetlabs/code/environments/production/manifests/site.pp:7:1 on node mark-inspiron.
On my node:
/opt/puppetlabs/bin/puppet module list
returns
/etc/puppetlabs/code/environment/production/modules
----- puppetlabs-firewall (v1.9.0)
On my puppet master at /etc/puppetlabs/code/environments/production/manifests/site.pp:
file {'/tmp/it_works.txt': # resource type file and filename
ensure => present, # make sure it exists
mode => '0644', # file permissions
content => "It works on ${ipaddress_eth0}!\n", # Print the eth0 IP fact
}
class { 'firewall': }
resources { 'firewall':
purge => true,
}
firewall { "051 asterisk-set-rate-limit-register":
string => "REGISTER sip:",
string_algo => "bm",
dport => '5060',
proto => 'udp',
recent => 'set',
rname => 'VOIPREGISTER',
rsource => 'true';
}
firewall { "052 asterisk-drop-rate-limit-register":
string => "REGISTER sip:",
string_algo => "bm",
dport => '5060',
proto => 'udp',
action => 'drop',
recent => 'update',
rseconds => '600',
rhitcount => '5',
rname => 'VOIPREGISTER',
rsource => true,
rttl => true;
}
The file part works but not firewall.
You need to install the modules on your master in a master setup with Puppet. They need to be somewhere in your modulepath. You can either place it in the modules directory within your $codedir (normally /etc/puppetlabs/code/modules) or in your directory environment modules directory (likely /etc/puppetlabs/code/environments/production/modules in your case since your cited site.pp is there). If you defined additional module paths in your environment.conf, then you can also place the modules there.
You can install/deploy them with a variety of methods, such as librarian-puppet, r10k, or code-manager (in Enterprise). However, the easiest method for you would be puppet module install puppetlabs-firewall on the master. Your Puppet catalog will then find the firewall class during compilation.
On a side note, that:
resources { 'firewall':
purge => true,
}
will remove any changes to associated firewall configurations (as defined by Puppet's knowledge of the system firewall configuration according to the module's definition of what the resource manages) that are not managed by Puppet. This is nice for eliminating local changes that people make, but it can also have interesting side effects, so be careful.

Puppet : exec[] : wget returned 8 instead of 0

I am completely new to Puppet and this is my first time writing code in puppet. I want to get a tar.gz file and then untar it to create the folder.
Here is my code:
file{ "${::filename}.tar.gz":
ensure => 'file',
mode => '0644',
notify => Exec['untar-file'],
}
exec{ 'download-file' :
command => "wget URL_FOR_TAR_GZ",
cwd => "PATH_WHERE_TO_STORE",
user => "my_name",
group => "our company name",
}
exec { 'untar-file':
command => "/bin/tar -xzvf tar_file_name",
cwd => "file_path",
creates => "foldername_to_be_createdc",
user => "my_name",
group => "our company name",
require => Exec['download-file']
}
As soon as I run this I get an error:
wget returned 8 instead of one of [0]" and "/Exec[download-file]/returns: change from notrun to 0 failed"
Where am I going wrong?

Containing a defined resource type in Puppet

I'm trying to create an instance of a defined resource type (::apt::ppa) that comes before other resources. I am using the PuppetLabs Apt Module.
When adding a new repository via the module, the defined type contains an exec statement that notifies apt::update so that any packages that might be required can be installed correctly. However, when I run my below code, the notify gets scheduled after I attempt to install Java, thereby causing the Java install to fail. I've tried putting anchors around the apt::ppa declaration, but that doesn't help. What else can I do?
class rap::java(
$version = '7',
) {
$package = "oracle-java${version}-installer"
apt::ppa { 'ppa:webupd8team/java': } ->
exec { 'accept-java-license':
command => "/bin/echo ${package} shared/accepted-oracle-license-v1-1 select true | /usr/bin/sudo /usr/bin/debconf-set-selections",
unless => "/usr/bin/debconf-show ${package} | grep 'shared/accepted-oracle-license-v1-1: true'",
} ->
class { '::java':
package => $package,
distribution => 'oracle-jre',
}
file_line { 'java_environment':
path => '/etc/environment',
line => "JAVA_HOME=\"/usr/lib/jvm/java-${version}-oracle\"",
}
}
I believe the issue is that you need to include the apt class within the class you've made to get the ordering right.
This works for me on a new Precise box:
class rap::java(
$version = '7',
) {
$package = "oracle-java${version}-installer"
include apt
apt::ppa { 'ppa:webupd8team/java':
package_manage => true,
}
exec { 'accept-java-license':
command => "/bin/echo ${package} shared/accepted-oracle-license-v1-1 select true | /usr/bin/sudo /usr/bin/debconf-set-selections",
unless => "/usr/bin/debconf-show ${package} | grep 'shared/accepted-oracle-license-v1-1: true'",
}
class { '::java':
package => $package,
distribution => 'oracle-jre',
require => [
Apt::Ppa['ppa:webupd8team/java'],
Exec["accept-java-license"],
]
}
file_line { 'java_environment':
path => '/etc/environment',
line => "JAVA_HOME=\"/usr/lib/jvm/java-${version}-oracle\"",
}
}
Log of run:
Notice: Compiled catalog for precise64 in environment production in 0.78 seconds
Notice: /Stage[main]/Apt/File[preferences]/ensure: created
Notice: /Stage[main]/Rap::Java/Exec[accept-java-license]/returns: executed successfully
Notice: /Stage[main]/Rap::Java/File_line[java_environment]/ensure: created
Notice: /Stage[main]/Apt/Apt::Setting[conf-update-stamp]/File[/etc/apt/apt.conf.d/15update-stamp]/ensure: defined content as '{md5}0962d70c4ec78bbfa6f3544ae0c41974'
Notice: /Stage[main]/Rap::Java/Apt::Ppa[ppa:webupd8team/java]/Package[python-software-properties]/ensure: created
Notice: /Stage[main]/Rap::Java/Apt::Ppa[ppa:webupd8team/java]/Exec[add-apt-repository-ppa:webupd8team/java]/returns: executed successfully
Notice: /Stage[main]/Apt::Update/Exec[apt_update]: Triggered 'refresh' from 1 events
Notice: /Stage[main]/Java/Package[java-common]/ensure: created
Notice: /Stage[main]/Java/Package[java]/ensure: created
Notice: Applied catalog in 39.58 seconds
To extend the question further, generally things that are blockers for a standard setup to run are usually moved into a run stage (documented here).
So I would probably move all of the various repo setup puppet code into pre run stage with other prerequisites (normally you put in repo setup), the run stage will always be run first before the main stage, so you don't have to worry about explictly setting requirements that repos are setup on each package. This makes making changes to repos and prerequisites a lot easier

Sequence of Execs in Puppet

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.

Resources