I'm trying to execute a script after deploy with Vagrant + Puppet:
include nginx
$nginx_conf_path = "${files_path}/${fqdn}/etc/nginx/sites-available"
nginx::site { 'test.example.com.conf' :
source => "${nginx_conf_path}/test.example.com.conf",
}
exec { 'install-letsencrypt.sh test.example.com':
require => [Nginx::Site['test.example.com.conf'], Class['profile::ssl']],
command => 'install-letsencrypt.sh test.example.com',
path => '/home/vagrant/bin/'
}
with ssl.pp:
class profile::ssl {
file { "/home/vagrant/bin" :
ensure => "directory",
owner => "vagrant",
group => "vagrant",
}
file { "/home/vagrant/bin/install-letsencrypt.sh":
ensure => "present",
owner => "vagrant",
group => "vagrant",
mode => 700,
source => "puppet:///modules/example/shared/install-letsencrypt.sh"
}
}
And install-letsencrypt.sh:
if [ ! -d "/opt/letsencrypt" ]; then
sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
fi
# ...etc
The profile::ssl works because /home/vagrant/bin/install-letsencrypt.sh is available, but when I try to exec it in puppet, I get:
==> test.example.com: Error: Deploying Let's encrypt for test.mojjo.fr
==> test.example.com: /home/vagrant/bin/install-letsencrypt.sh: line 11: sudo: command not found
==> test.example.com: /home/vagrant/bin/install-letsencrypt.sh: line 14: mkdir: command not found
==> test.example.com: /home/vagrant/bin/install-letsencrypt.sh: line 17: sudo: command not found
==> test.example.com: /home/vagrant/bin/install-letsencrypt.sh: line 23: sudo: command not found
==> test.example.com: /home/vagrant/bin/install-letsencrypt.sh: line 25: sudo: command not found
What am I doing wrong? I tried with absolute executable paths (/usr/bin/sudo instead of sudo) but it doesn't work either. If I ssh test.example.com and run it there, it also works, so the problème is not in the script.
Thanks in advance
I had this same issue to run some script so I did
exec { 'run-script':
command => "bash -c 'install-letsencrypt.sh test.example.com'",
....
}
Related
I use Fortinet for firewall automation, but i get the error "Error reading running config" . I already followed this website: https://github.com/ansible/ansible/issues/33392
But do not find any solution. Please tell me what am I doing wrong ?
Ansible version: 2.7.0
Python version: 2.7.5
Fortinet: 60E
FortiOS version: 6.0.2
Here is what I am trying:
FortiOS.yml playbook:
---
- name: FortiOS Firewall Settings
hosts: fortiFW
connection: local
vars_files:
- /etc/ansible/vars/FortiOS_Settings_vars.yml
tasks:
- name: Backup current config
fortios_config:
host: 192.168.1.99
username: admin
password: Password#123
backup: yes
backup_path: /etc/ansible/forti_backup
Here is what I get as error:
ok: [192.168.1.99] META: ran handlers Read vars_file
'/etc/ansible/vars/FortiOS_Settings_vars.yml'
TASK [Backup current config]
**************************************************************************************************************************************************************************************************************** task path: /etc/ansible/FortiOS_Settings_test.yml:8 <192.168.1.99>
ESTABLISH LOCAL CONNECTION FOR USER: root <192.168.1.99> EXEC /bin/sh
-c 'echo ~root && sleep 0' <192.168.1.99> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226" && echo
ansible-tmp-1539674386.05-16470854685226="echo
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226" ) &&
sleep 0' Using module file
/usr/lib/python2.7/site-packages/ansible/modules/network/fortios/fortios_config.py
<192.168.1.99> PUT
/root/.ansible/tmp/ansible-local-6154Uq5Dmw/tmpt6JukB TO
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
<192.168.1.99> EXEC /bin/sh -c 'chmod u+x
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
&& sleep 0' <192.168.1.99> EXEC /bin/sh -c '/usr/bin/python
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
&& sleep 0' <192.168.1.99> EXEC /bin/sh -c 'rm -f -r
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/ >
/dev/null 2>&1 && sleep 0' The full traceback is: WARNING: The below
traceback may not be related to the actual failure. File
"/tmp/ansible_fortios_config_payload_b6IQmy/main.py", line 132, in
main
f.load_config(path=module.params['filter']) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 212, in
load_config
config_text = self.execute_command(command) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 154, in
execute_command
output = output + self._read_wrapper(o) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 120, in
_read_wrapper
return py23_compat.text_type(data)
fatal: [192.168.1.99]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"backup": true,
"backup_filename": null,
"backup_path": "/etc/ansible/forti_backup",
"config_file": null,
"file_mode": false,
"filter": "",
"host": "192.168.1.99",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"src": null,
"timeout": 60,
"username": "admin",
"vdom": null
}
},
"msg": "Error reading running config" }
When working with this module, I had the same issue. I looked into the source code of the module, and found that this error occurs when filter is set to "" -> empty string. You can get facts about the device when changing filter to something like "firewall address". But then you will only get back the options from exactly that, like if you would've typed "show firewall address" on the CLI of the device.
I'm currently working on a solution to use Ansible for FortiGate automation, but it's not looking good. E.g. FortiGates additionally do not support Netconf, so you can't use Netconf to send commands to the device.
So therefore, you're not doing anything wrong, but the modules is either not optimized, or I guessed that maybe the full-configuration is too big to be read by the module, so that you have to use the filter option to shrink it.
I have a bash command that will return either 1 or 0. I want to run said command from puppet:
exec { 'Check if Thinkpad':
command => 'sudo dmidecode | grep -q ThinkPad && echo 1 || echo 0',
path => '/usr/bin/:/bin/bash/',
environment => "HOME=/root"
}
Is there a way I can include a file using puppet only if my command returned 1?
file { '/etc/i3/config':
source => 'puppet:///modules/i3/thinkpad',
owner => 'root',
group => 'root',
mode => '0644',
}
You can use an external fact to use the bash script as is. Inside the module's facts.d directory, you could place the script.
#!/bin/bash
if [ dmidecode | grep -q ThinkPad ]
echo 'is_thinkpad=true'
else
echo 'is_thinkpad=false'
fi
You can also use a custom fact inside the lib/facter directory of your module.
Facter.add(:is_thinkpad) do
confine kernel: linux
setcode do
`dmidecode | grep -q ThinkPad && echo true || echo false`
end
end
In both cases, the fact name of is_thinkpad follows the convention for the nomenclature of boolean facts for types of systems. You can then update the code in your manifest for this boolean.
if $facts['is_thinkpad'] == true {
file { '/etc/i3/config':
source => 'puppet:///modules/i3/thinkpad',
owner => 'root',
group => 'root',
mode => '0644',
}
}
This will provide you with the functionality you desire.
https://docs.puppet.com/facter/3.6/custom_facts.html#adding-custom-facts-to-facter
https://docs.puppet.com/facter/3.6/custom_facts.html#external-facts
You will probably need to turn your bash script into a "custom fact" -- which is something I've only done once and don't fully understand enough to teach you how.
I want to say that the easiest way to set up a custom fact is to put your script into /etc/facter/facts.d/ on the agent machine, and make sure it ends with a line that says
echo "thinkpadcheck=1"
or
echo "thinkpadcheck=0"
You can test it with (note: you must be root)
sudo facter -p | grep think
and it should return
thinkpadcheck => 1
But once you have done that, then your puppet script can say
if $thinkpadcheck == 1
{
file { '/etc/i3/config':
source => 'puppet:///modules/i3/thinkpad',
owner => 'root',
group => 'root',
mode => '0644',
}
}
else
{
notify { "thinkpadcheck failed for $hostname" : }
}
I'd like to share another method I found in the Puppet Cookbook 3rd edition (page 118):
message.rb
#!/usr/bin/env ruby
puts "This runs on the master if you are centralized"
Make your script executable with:
sudo chmod +x /usr/local/bin/message.rb
message.pp
$message = generate('/usr/local/bin/message.rb')
notify { $message: }
Then run:
puppet apply message.pp
This example uses a ruby script but any type of script including a basic shell script, as was needed in my case, can be used to set a variable in puppet.
Similar to this question: Passing variable to a shell script provisioner in vagrant
I want to pass variables to a shell script provisioner but I want to set these variables on the command line when I call the provisioner. Is this possible?
This is what I would try - I guess there are possibilities as Vagrantfile is a ruby script, you can use most of ruby possibilities
Be careful though as vagrant might need to check for variables, for example when doing vagrant up arg1 arg2, it expects arg1 and arg2 to be machine names defined in Vagrantfile and will raise an error as it cannot find it
So you would need to pass those variables like
vagrant --arg1 --arg2 up
To read them you could
# -*- mode: ruby -*-
# vi: set ft=ruby :
v1 = ARGV[0]
v2 = ARGV[1]
array_arg = [v1, v2]
Vagrant.configure("2") do |config|
blabla config
array_arg.each do |arg|
config.vm.provision "shell", run: "always" do |s|
s.inline = "echo $1"
s.args = arg
end
end
end
for example, the execution would give
fhenri#machine:~/project$ vagrant --arg1 --arg2 up
. . . . .
==> default: Running provisioner: shell...
default: Running: inline script
==> default: stdin: is not a tty
==> default: --arg1
==> default: Running provisioner: shell...
default: Running: inline script
==> default: stdin: is not a tty
==> default: --arg2
In your Vagrantfile, add the following -
{
"PROVISION_PARAMS" => "some_default_values",
}.each { |key, value| ENV[key] = value if ENV[key] == nil }
These arguments can now be passed to shell script provisioner in the following way -
config.vm.provision :shell, privileged: true, run: "always",
:path => "../../scripts/script.ps1",
:args => ENV['PROVISION_PARAMS']
You can now provide command line arguments to this script in the following manner -
$ PROVISION_PARAMS=' param1 param2 "param 3" ' vagrant provision
And the script will take default values if these parameters are not specified.
How to exec a command if directory does not exists in puppet file?
exec { "my_exec_task":
command => "tar zxf /home/user/tmp/test.tar.gz",
unless => "test -d /home/user/tmp/new_directory",
path => "/usr/local/bin/:/bin/",
}
I get error: "Could not evaluate: Could not find command 'test'". Also is this the best practice to check if directory does not exists?
test work for me at /usr/bin, so adding it to path could solve error.
unless => 'bash -c "test -d /home/user/tmp/new_directory"',
Should work too. But I think the correct way is to use creates:
exec { "my_exec_task":
command => "tar zxf /home/user/tmp/test.tar.gz",
creates => "/home/user/tmp/new_directory",
path => "/usr/local/bin/:/bin/",
}
Actual problem is in path:
path => [ '/usr/local/bin', '/sbin', '/bin', '/usr/sbin', '/usr/bin' ]
I'm using this Laravel Vagrant: https://github.com/bryannielsen/Laravel4-Vagrant and I want to add PHPUNIT and some other PEAR packages.
I added this line on manifests/phpbase.pp
include pearpackages
I created this file puppet/modules/pearpackages/manifests/init.pp:
class pearpackages {
exec {"pear upgrade":
command => "/usr/bin/pear upgrade",
require => Package['php-pear'],
returns => [ 0, '', ' ']
}
# set channels to auto discover
exec { "pear auto_discover" :
command => "/usr/bin/pear config-set auto_discover 1",
require => [Package['php-pear']]
}
exec { "pear update-channels" :
command => "/usr/bin/pear update-channels",
require => [Package['php-pear']]
}
exec {"pear install phpunit":
command => "/usr/bin/pear install --alldeps pear.phpunit.de/PHPUnit",
creates => '/usr/bin/phpunit',
require => Exec['pear update-channels']
}
# install phploc
exec {"pear install phploc":
command => "/usr/bin/pear install --alldeps pear.phpunit.de/phploc",
creates => '/usr/bin/phploc',
require => Exec['pear update-channels']
}
# install phpcpd
exec {"pear install phpcpd":
command => "/usr/bin/pear install --alldeps pear.phpunit.de/phpcpd",
creates => '/usr/bin/phpcpd',
require => Exec['pear update-channels']
}
# install phpdcd
exec {"pear install phpdcd":
command => "/usr/bin/pear install --alldeps pear.phpunit.de/phpdcd-beta",
creates => '/usr/bin/phpdcd',
require => Exec['pear update-channels']
}
# install phpcs
exec {"pear install phpcs":
command => "/usr/bin/pear install --alldeps PHP_CodeSniffer",
creates => '/usr/bin/phpcs',
require => Exec['pear update-channels']
}
# install phpdepend
exec {"pear install pdepend":
command => "/usr/bin/pear install --alldeps pear.pdepend.org/PHP_Depend-beta",
creates => '/usr/bin/pdepend',
require => Exec['pear update-channels']
}
# install phpmd
exec {"pear install phpmd":
command => "/usr/bin/pear install --alldeps pear.phpmd.org/PHP_PMD",
creates => '/usr/bin/phpmd',
require => Exec['pear update-channels']
}
# install PHP_CodeBrowser
exec {"pear install PHP_CodeBrowser":
command => "/usr/bin/pear install --alldeps pear.phpqatools.org/PHP_CodeBrowser",
creates => '/usr/bin/phpcb',
require => Exec['pear update-channels']
}
}
After, I make a vagrant provision
It seems that is all well configured, but when I go to localhost:8888 the page is always loading and not show me the content.
I don't know what I'm doing bad, but I need your help please, the system configuration is not my specialty
Have you tried using PuPHPet to generate your Puppet manifests? You can enter PEAR modules under the Languages section.
I´ve found the solution.
There are some incompatibility with Vagrant and VirtualBox in some versions. I don´t know if the issue is for the Guests Aditions.
With vagrant 1.6.2 and VirtualBox 4.3.12 works fine.