Copy files using puppet with relative path - puppet

I am trying to write code with puppet and vagrant, and am unable to find how to copy a file from the directory containing the manifest to the target server.
In ansible I used this:
- name: Copy public key
copy:
src: ./myKey
dest: /home/user/.ssh/authorized_keys
I would like to do something like this with puppet
- file { 'myKey':
path => '/home/user/.ssh/authorized_keys',
ensure => file,
source => ./myKey }
I understand how to make this work using absolute path, but would like to use relative path here as my script will be pulled down with a git clone and run on another machine that will have different directory setups.
Vagrant.configure("2") do |config|
config.vm.network "private_network", ip: "192.168.1.1", auto_config: true
config.vm.box = "puppetlabs/centos-7.2-64-puppet-enterprise"
config.vm.provision "puppet" do |puppet|
puppet.manifest_file = "srv_site.pp"
end
end

In order to copy a file in puppet you need to put the file in the module path under files. So if your module is named mymodule the file should go here:
./mymodule/files/mykey
and in the module the file is copied by
file { 'mykey':
ensure => file,
path => '/home/user/.ssh/authorized_keys',
source => "puppet:///modules/${module_name}/mykey"
}
you cannot point source to a different place on the puppet master, unless you set up a file server mount point on the pupper master see https://docs.puppet.com/puppet/4.10/file_serving.html.
but the source can point to other places see https://docs.puppet.com/puppet/4.10/types/file.html#file-attribute-source.

Related

Find and copy files with ansible

I want to make a script with ansible, to search on folder "/software" all the files, that were edited in the last day, then move them to "/tmp"
This my code so far (redhat 7.4):
- name: recurse path
find:
path: /software
recurse: yes
file_type: file
age: 1d
register: files
- name: copy files to tmp
copy:
src: ~/{{files}}
dest: /tmp
I get the error:
an exeption occurred during task execution ... could not find or access '~{u'files': []}, u'changed': False, 'failed': False, u'examined': 4....
The folders have full access, so I dont think its permissions.
What am I doing wrong?
As documented, the returned value of the find module is an object containing the list of found files under the files keyword.
You cannot use it directly: copy module takes only 1 file or folder as src, so you have to loop over all the files:
- name: check the content and structure of the variable
debug:
var: files
- name: copy files to tmp
copy:
src: "{{item.path}}"
dest: /tmp
with_items: "{{files.files}}"
It's always a good practice to debug a var after register while developing to check it's structure (so you can find how to use it) and it's content (in your case, looks like the file list is empty).
BTW: you need to know that the find module search on the remote host but, by default, the copy module copies from the ansible executor machine, so in your case, the src may not exists! So if you are copying from local to remote, simply add delegate_to: localhost and run_once: yes to your find task, otherwise you need to use the remote_src: yes parameter on the copy task.

Puppet creates a broken symlink

For example I have a symlink /etc/foo/folder11/some/link.txt which points to etc/foo/folder12/some/file.txt.
And in puppet I have the following
ensure_resource('file', "/etc/bar/link.txt", {
owner => $someUser,
mode => '0444',
source => `/etc/foo/folder11/some/link.txt`,
})
After puppet run it creates a broken symlink /etc/bar/link.txt which points to ../../folder12/some/file.txt.
Why does it create so strange symlink? And how can I force puppet to create /etc/foo/link.txt symlink which should point to the same file to which /etc/foo/folder11/some/link.txt points to ?
Note that I don't use ensure => link because sometimes /etc/foo/folder11/some/link.txt may be a regular file and in this case /etc/bar/link.txt should be a copy of this file.
As it turned out the problem was in /etc/foo/folder11/some/link.txt which was a relative symlink. I changed it to be absolute and now it works fine.

How can I refer to the current puppet module's files directory?

This is most likely an anti-pattern, but I'd like to know nonetheless:
I need to extract a tgz which is in puppet and then move the contents somewhere else. Is it possible, in a puppet exec { }, to refer to the file where it is stored on disk?
For example, puppet is available at /usr/local/puppet, and the tgz file I need it in /usr/local/puppet/modules/components/files/file.tgz. In the exec { } can I do something like command => "/bin/cp $modules/components/files/file.tgz /somewhere_else" ? Or do I have to declare a file { source => "..." } block first?
Both approaches are correct if you run puppet with puppet apply.
In master-agent architecture using exec to copy file probably will not work at all.
In my opinion using file resource is more "puppet-like" but is has one significant drawback.
You can use:
file { '/some_path/somewhere_else':
source => '/usr/local/puppet/modules/components/files/file.tgz',
}
This will create file /some_path/somewhere_else with the same content as /usr/local/puppet/modules/components/files/file.tgz (it will make a copy of the original file).
But if /some_path doesn't not exist in the file system, the command will fail.
If you are working with tgz files you can also consider using some of the archive puppet modules e.g gini.
UPDATE:
I can propose two approaches:
Use puppet file server to serve files (or define module path for old puppet versions). Next just use it e.g:
file { '/some_path/somewhere_else':
source => "puppet:///modules/components/file.tgz',
}
Define custom facter fact 1, 2 that points path in your filesystem containing required files. E.g:
file { '/some_path/somewhere_else':
source => "${::my_custom_fact}/some_path/file.tgz',
}
I do not think that any of the core facts might be useful for you.

Symlinking a vagrant shared folder with puppet

I'm needing to recreate a setup on an old server with vagrant where we served sites within the home directory. Its not possible to set a shared folder to /home in vagrant as this will remove the vagrant user. I therefore would like to create a shared folder that is actually a symlink to the home directory.
If I create a shared directory like this in my Vagrantfile:
config.vm.share_folder "v-www", "/webroot", "/Users/me/sites/vagrant"
and then try and create a symlink with puppet overwriting this directory like this:
class misc {
file { '/webroot':
ensure => 'link',
target => '/home',
force => true,
}
}
It throws an error:
Error: Could not remove existing file
Error: /Stage[main]/Misc/File[/webroot]/ensure: change from directory
to link failed: Could not remove existing file
When I log into the box and attempt this manually this also fails as i'm not actually able to remove the webroot - I assume this is because its created as some kind nfs share or something like that.
Any ideas how I can get around this?
Try adding a replace:
class misc {
file { '/webroot':
ensure => 'link',
target => '/home',
force => true,
replace => true,
}
}

Sourcing Puppet files from outside of modules

I'm installing a package from a module (Nginx in this specific case) and would like to include a configuration file from outside of the module, i.e. from a top level files directory parallel to the top level manifests directory. I don't see any way to source the file though without including it in a module or in my current Vagrant environment referring to the absolute local path.
Does Puppet allow for sourcing files from outside of modules as described in the documentation?
if I understand your question correctly, you can.
In your module a simple code like this
file { '/path/to/file':
ensure => present,
source => [
"puppet:///files/${fqdn}/path/to/file",
"puppet:///files/${hostgroup}/path/to/file",
"puppet:///files/${domain}/path/to/file",
"puppet:///files/global/path/to/file",
],
}
will do the job. The /path/to/file will be sourced using a file located in the "files" Puppet share.
(in the example above, it search in 4 different locations).
update maybe you're talking about a directory to store files which is not shared by Puppet fileserver (look at http://docs.puppetlabs.com/guides/file_serving.html), and in this case you can't i think, Vagrant or not, but you can add it to your Puppet fileserver to do it. I thinks it's the best (and maybe only) way to do it.
If you have a number of Vagrant VMs you can simply store files within your Vagrant project directory (containing your VagrantFile).
This directory is usually available to all VMs as /vagrant within the VM on creation.
If you want other directories on your computer to be available to your VMs just add the following to your VagrantFile
# see http://docs.vagrantup.com/v1/docs/config/vm/share_folder.html
config.vm.share_folder "v-packages", "/vagrant_packages", "../../dpkg"
Then to use the files within puppet you can simply treat them as local files to the VM
# bad example, bub basically use 'source => 'file:///vagrant/foo/bar'
file { '/opt/cassandra':
ensure => directory,
replace => true,
purge => true,
recurse => true,
source => 'file:///vagrant/conf/dist/apache-cassandra-1.2.0',
}
This is probably only wise to do if you only using local puppet manifests/modules.
Probably too late to help bennylope, but for others who happen across this question, as I did before figuring it out for myself ...
Include stuff like this in your Vagrantfile ...
GUEST_PROVISIONER_CONFDIR = "/example/destination/path"
HOST_PROVISIONER_CONFDIR = "/example/source/path"
config.vm.synced_folder HOST_PROVISIONER_CONFIDIR, GUEST_PROVISIONER_CONFDIR
puppet.options = "--fileserverconfig='#{GUEST_PROVISIONER_CONFDIR}/fileserver.conf'"
Then make sure /example/source/path contains the referenced fileserver.conf file. It should look something like ...
[foo]
path /example/destination/path
allow *
Now, assuming example-file.txt exists in /example/source/path, the following will work in your manifests:
source => "puppet:///foo/example-file.txt",
See:
Puppet configuration reference entry for fileserverconfig
Serving Files From Custom Mount Points

Resources