How do I make puppet copy a file only if source exists? - vagrant

I am trying to provision a vagrant VM to allow users to supply their own bash_profile.local but I don't want this file tracked in the vm's vcs repo. I have a tracked bash_profile.local.dist file that they can rename. How can I tell puppet to only create a file if the source file exists? It is currently working correctly but logs an error during provisioning and this is what I'm trying to avoid.
This is the manifest:
class local
{
file { '.bash_profile.local':
source => 'puppet:///modules/local/bash_profile.local',
path => '/home/vagrant/.bash_profile.local',
replace => false,
mode => 0644,
owner => 'vagrant',
group => 'vagrant',
}
}

You could abuse file in this way :
$a = file('/etc/puppet/modules/local/files/bash_profile.local','/dev/null')
if($a != '') {
file { '.bash_profile.local':
content => $a,
...
}
}

This is not exactly what you asked but you can supply multiple paths in the source, so you can have a default empty file if the user didn't supplied his own.
class local
{
file { '.bash_profile.local':
source => [
'puppet:///modules/local/bash_profile.local',
'puppet:///modules/local/bash_profile.local.default'
],
path => '/home/vagrant/.bash_profile.local',
replace => false,
mode => 0644,
owner => 'vagrant',
group => 'vagrant',
}
}

You can try something like this:
file { 'bash_profile.local':
ensure => present,
source => ['puppet:///modules/local/bash_profile.local', '/dev/null'],
path => '/home/vagrant/.bash_profile.local',
before => Exec['clean-useless-file'],
}
exec { 'clean-useless-file':
command => 'rm .bash_profile.local',
onlyif => 'test -s .bash_profile.local',
cwd => '/home/vagrant',
path => '/bin:/usr/bin',
}
If the admin don't make a copy of ".bash_profile.local" available in "modules/local/bash_profile.local", the file resource will use the second source and then create a blank file. Then, the "onlyif" test fails and the exec will remove the useless blank file.
Used this way this code can be a little cumbersome, but it's better than a provisioning failure. You may evaluate if retaining a blank .bash_profile.local file can be okay in your case. I normally use a variation of this, with wget instead of rm, to get a fresh copy of the file from the internet if it was not already made available as a source.
If you're using puppetmaster, be aware you can use it to provision the own server, presenting two versions of the catalog, according to the .bash_profile.local is present or not.

Related

Convert puppet manifest config into hiera

I installed corosync-pacemaker cluster via puppet. Now I would to like keep my data into hiera file. How should I convert cs_primitive section into yaml file?
cs_primitive { 'nfsshare_fs':
primitive_class => 'ocf',
primitive_type => 'Filesystem',
provided_by => 'heartbeat',
parameters => { 'device' => '/dev/disk/lvname', 'directory' =>
'/share', 'fstype' => 'ext4' },
}->
I tried the below code but it didn't work.
corosync::cs_primitive:
'nfsshare_fs':
primitive_class: 'ocf'
primitive_type: 'Filesystem'
provided_by: 'heartbeat'
parameters:
device: '/dev/disk/by-id/lvname'
directory: '/share'
fstype: 'ext4'
It won't work because cs_primitive is a resource type, like, for example, File.
If you want to use it from Hiera, then you could create a class that wraps cs_primitive applying and then connect this class with Hiera.
classes:
- my_class
my_class::param1: value1
my_class::param2: value2
Useful links:
https://puppet.com/docs/puppet/7/lang_defined_types.html
https://puppet.com/docs/puppet/7/lang_classes.html

Laravel change filesystem disks path on run time

I am aware of the filesystems.php to create disks and I'm currently using it, having ~~ 20 disks configured.
I have a new problem with these, I'm currently trying to prefix to every disk, a string. The problem is that the paths are being saved when the php artisan config:cache is run but I need to change them on run time, as n example, for User Sergio it would need to append Sergio/ to the following disk for example:
//filesystems.php
'random' => [
'driver' => 'local',
'root' => storage_path('app/random'),
],
Then
Storage::disk("random")->getDriver()->getAdapter()->getPathPrefix();
//outputs /var/www/html/project/storage/app/random
and the goal is setting configurations in for example the middleware i'm currently setting the tentant database already like this
//Middleware
Config::set('database.connections.tenant.database', "Sergio");
DB::reconnect('tenant');
I can currently set the paths correctly with
Config::set('filesystems.disks.random.root',storage_path('app/Sergio/random'));
But i'm worried since that if before that line I try to reach to the path, the storage saves the initial path in memory instead of re-fetching it after it is altered.
For example. doing this without any middleware.
$fullPath1 = Storage::disk("random")->getDriver()->getAdapter()->getPathPrefix();
Config::set('filesystems.disks.random.root',storage_path('app/Sergio/random'));
$fullPath2 = Storage::disk("random")->getDriver()->getAdapter()->getPathPrefix();
What was intended to happen is that $fullPath1 would output the initial path which is /var/www/html/project/storage/app/random and then $fullPath2 would output /var/www/html/project/storage/app/Sergio/random
Is there any way of letting the Storage know that I've changed the disks local paths?
How about adding a new config instead of updating the already loaded one, something like this:
private function addNewDisk(string $diskName)
{
config(['filesystems.disk.' . $diskName => [
'driver' => 'local',
'root' => storage_path('app/' . $diskName),
]]);
}
and prior to using the Storage facade, call above method that way the config will be updated and when you use new disk, it will try to resolve again based on updated config.
{
....
$this->addNewDisk('new_random');
Storage::disk('new_random')->get('abc.txt'); // or any another method
...
}

Puppet file resource require archive resource

I am using Puppet for doing my Vagrant provisioning. I used the archive module at https://forge.puppet.com/puppet/archive/types to download and extract glassfish like this:
archive { '/tmp/glassfish-4.1.1.zip':
ensure => present,
extract => true,
extract_path => '/opt/',
source => 'http://download.java.net/glassfish/4.1.1/release/glassfish-4.1.1.zip',
cleanup => true,
creates => '/opt/glassfish4',
}
After that resource is applied, I want to move a file into the newly created glassfish directory like this
file { 'domain.xml':
ensure => file,
path => '/opt/glassfish4/glassfish/domains/domain1/config/domain.xml',
source => 'puppet:///modules/glassfish/domain.xml',
}
I want to require in the file move resource that the extraction was already done, since the extraction is not creating a file, but rather a directory. Something like
require => FILE['..']
is not working.
You should add a require on the archive task so your file task will be something like
file { 'domain.xml':
ensure => file,
path => '/opt/glassfish4/glassfish/domains/domain1/config/domain.xml',
source => 'puppet:///modules/glassfish/domain.xml',
require => Archive['/tmp/glassfish-4.1.1.zip'],
}
so that the copy of the domain.xml file will be done after the archive task.

Pass "yes" to command given in a text file

I'm using rbvmomi gem to automate vsphere in ruby. I'm using vmware API StartProgramInGuest to run commands. The commands are given in a text file which is passed as an argument to GuestProgramSpec. One of the commands in the file requires a confirmation. Since the commands are passed in a text file, I'm not sure how to pass "yes" to the command. Any help would be appreciated.
gom = vim.serviceContent.guestOperationsManager
guest_auth = RbVmomi::VIM::NamePasswordAuthentication(
:interactiveSession => false,
:username => "user",
:password => "pass"
)
prog_spec = RbVmomi::VIM::GuestProgramSpec(
:programPath =>"/opt/system/bin/ssh",
:arguments => "-s /opt/system/etc/cli/default/main.par -f /home/admin/local.txt"
)
id = gom.processManager.StartProgramInGuest(
:vm => vm, :auth => guest_auth, :spec => prog_spec
)
Contents of local.txt :
show version > /home/admin/veriosn-1.txt
application upgrade appbundle.tar.gz local
show version > /home/admin/version-2.txt

how vagrantfile stores the changes in vagrant machine?

I am developing an application with PhP and client asked me to set up a vagrant machine and install every needed extensions and modules, so that with just one Vagrant up command the client will have the same environment as I have,
I firstly installed a vagrant machine from one of the boxes lsit
vagrant box add ubuntu1 http://goo.gl/KwQSa2
Then I run these commands:
vagrant init ubuntu1
vagrant up
in the directory that I made this file there is only a vagranrfile
The Question:
I need to know if I make any changes to my server for example, installing php or mysql how it is going to saved in the setting so that if I just give this file to my client he will be able to have an identical machine to mine with everything installed?
I mean there will be any changes to vagrantfile or I made some mistake and I had to install a machine with puppet?
thanks in advance
No, the vagrant file is not going to change as you install things in the VM.
If you want your client to have the same machine as you, you'll have to avoid installing softwares through the VM's shell. You should only use the provisioner, for everything, even mysql tables, apache virtual hosts etc..
And don't use vagrant box add ubuntu1 http://goo.gl/KwQSa2, add the box's url to the vagrantfile with:
config.vm.box_url = "http://goo.gl/KwQSa2"
Example puppet provisioning for a mysql/php server:
group { 'puppet':
ensure => 'present',
}
#
# Apache configuration
#
class { 'apache' :
default_mods => false,
default_confd_files => false,
mpm_module => 'prefork',
default_vhost => false,
sendfile => 'Off'
}
class { 'apache::mod::php' : } # mod_php
class { 'apache::mod::rewrite' : } # mod_rewrite
# VHost configuration
apache::vhost { 'dev.XXX.fr' :
port => '80',
docroot => '/var/sites/myXXX/web',
access_log => true,
access_log_file => 'XXX_access.log',
error_log => true,
error_log_file => 'XXX_error.log',
aliases => [{alias => '/myXXX', path => '/var/sites/toto/web'}],
directories => [{path => '/var/sites/myXXX/web', 'allow_override' => ['FileInfo', 'Indexes']}, {path => '/var/sites/toto/web', 'allow_override' => ['FileInfo', 'Indexes']}]
}
#
# Mysql configuration
#
class { '::mysql::server' :
root_password => 'XXX',
databases => {
'XXX' => {
ensure => 'present',
charset => 'utf8'
}
},
users => {
'XXX#localhost' => {
ensure => 'present',
password_hash => 'XXX' # XXXmdp
}
},
grants => {
'XXX#localhost/XXX' => {
ensure => 'present',
options => ['GRANT'],
privileges => ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE'],
table => 'XXX.*',
user => 'XXX#localhost'
}
}
}
class { '::mysql::client' : }
package { 'php5-mysql' :
require => [Class['apache::mod::php'], Class['::mysql::server']],
ensure => 'present'
}
You will need the following modules:
apache
concat
mysql
stdlib
The puppet config above is just for the example, I highly encourage you to read there documentation which is really well done: http://docs.puppetlabs.com/learning/introduction.html
Honestly, puppet is a great tool, take the time to learn it.
One more thing, avoid using the shell provisionner, the commands are executed everytime you run "vagrant provision", puppet only executes changes. (I only use the shell provisionner for apt-get update and apt-get upgrade)
Vagrantfile is a recipe which tells Vagrant how to set up your machine. In a way, it serves as an installation automation tool (and of course does much more as well). If you do any changes to the machine after it was created, Vagrant would not know about that.
What I do is I create Vagrantfile and inside of it I specify a shell script which Vagrant will execute only once, after machine boots the first time.
VAGRANTFILE_API_VERSION = "2"
$bootstrap = <<SCRIPT
# Installing all dependencies and other required software.
# Add "-y" switch to make sure installation is fully automatic.
apt-get install -y python-software-properties
# Any other stuff I might want to do (like edit conf files)
...
SCRIPT
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "precise64"
config.vm.provision "shell", inline: $bootstrap
end
See the doc for config.vm.provision.
I do this inline for convienience, so all configuration is still kept in only one file.
Of course any configuration which is supported directly by Vagrant, is better kept out of this $bootstrap script.

Resources