Puppet file resource require archive resource - vagrant

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.

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 backup with spatie/laravel-backup - There is no disk set for the backup destination - Google Cloud Storage

I'm unable to backup to GCS from Laravel app
using spatie/laravel-backup
$ php artisan backup:run
Starting backup...
Dumping database reviewbooster...
Determining files to backup...
Zipping 720 files...
Created zip containing 720 files. Size is 29.86 MB
Copying zip to disk named gcs...
Copying zip failed because: There is no disk set for the backup destination.
Backup completed!
filesystems.php
'gcs' => [
'driver' => 'gcs',
'project_id' => env('GOOGLE_CLOUD_PROJECT_ID', 'project-id'),
'key_file' => env('GOOGLE_CLOUD_KEY_FILE', null), // optional: /path/to/service-account.json
'bucket' => env('GOOGLE_CLOUD_STORAGE_BUCKET', 'bucket'),
'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', null), // optional: /default/path/to/apply/in/bucket
'storage_api_uri' => env('GOOGLE_CLOUD_STORAGE_API_URI', null), // see: Public URLs below
'visibility' => 'private', // optional: public|private
],
backup.php
'destination' => [
/*
* The filename prefix used for the backup zip file.
*/
'filename_prefix' => '',
/*
* The disk names on which the backups will be stored.
*/
'disks' => [
'gcs',
],
],
I just had this same problem.
For me, the root cause was that my .env file had incorrect variables names that didn't match what Laravel expected in config/filesystems.php.
For example, I had:
AWS_KEY=xxx
AWS_SECRET=xxx
AWS_REGION=us-east-1
AWS_BUCKET=xxx
instead of:
AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=xxx
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=xxx
P.S. Once I fixed that, I tried running the backup again and got a new error (403 Forbidden, Access Denied, Error executing "PutObject").
So then I visited https://console.aws.amazon.com/iam/home?region=us-east-1#/users/ and clicked "Add inline policy" for the relevant user. (See this answer.)

Create a file descriptor in ruby

I am writing a script will perform various tasks with DSV or positional files. These tasks varies and are like creating an DB table for the file, or creating a shell script for parsing it.
As I have idealized my script would receive a "descriptor" as input to perform its tasks. It then would parse this descriptor and perform its tasks accordingly.
I came up with some ideas on how to specify the descriptor file, but didn't really manage to get something robust - probably due my inexperience in ruby.
It seems though, the best way to parse the descriptor would be using ruby language itself and then somehow catch parsing exceptions to turn into something more relevant to the context.
Example:
The file I will be reading looks like (myfile.dsv):
jhon,12343535,27/04/1984
dave,53245265,30/03/1977
...
Descriptor file myfile.des contains:
FILE_TYPE = "DSV"
DSV_SEPARATOR = ","
FIELDS = [
name => [:pos => 0, :type => "string"],
phone => [:pos => 1, :type => "number"],
birthdate => [:pos => 2, :type => "date", :mask = "dd/mm/yyyy"]
]
And the usage should be:
ruby script.rb myfile.des --task GenerateTable
So the program script.rb should load and parse the descriptor myfile.des and perform whatever tasks accordingly.
Any ideas on how to perform this?
Use YAML
Instead of rolling your own, use YAML from the standard library.
Sample YAML File
Name your file something like descriptor.yml, and fill it with:
---
:file_type: DSV
:dsv_separator: ","
:fields:
:name:
:pos: 0
:type: string
:phone:
:pos: 1
:type: number
:birthdate:
:pos: 2
:type: date
:mask: dd/mm/yyyy
Loading YAML
You can read your configuration back in with:
require 'yaml'
settings = YAML.load_file 'descriptor.yml'
This will return a settings Hash like:
{:file_type=>"DSV",
:dsv_separator=>",",
:fields=>
{:name=>{:pos=>0, :type=>"string"},
:phone=>{:pos=>1, :type=>"number"},
:birthdate=>{:pos=>2, :type=>"date", :mask=>"dd/mm/yyyy"}}}
which you can then access as needed to configure your application.

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.

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

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.

Resources