Run `apt-get update` before installing other packages with Puppet - puppet

I'm trying to create puppet module which automates installation of zend server CE, this is not important here, but steps are as following
update /etc/apt/source.list
download repos key via wget
do apt-get update
do apt-get install zend-server-ce-5.2
I have init.pp file
class zendserverce {
# https://github.com/puppetlabs/puppetlabs-stdlib
file_line { 'debian_package':
path => '/etc/apt/sources.list',
line => 'deb http://repos.zend.com/zend-server/deb server non-free'
}
exec { "wget http://repos.zend.com/zend.key -O- |apt-key add -":
path => ["/usr/bin", "/usr/sbin"]
}
exec { "apt-get update":
command => "/usr/bin/apt-get update",
onlyif => "/bin/sh -c '[ ! -f /var/cache/apt/pkgcache.bin ] || /usr/bin/find /etc/apt/* -cnewer /var/cache/apt/pkgcache.bin | /bin/grep . > /dev/null'",
}
package { "zend-server-ce-php-5.2":
ensure => "latest"
}
}
Seems that puppet runs commands in different order then I need. Is there any way how to for tell him to run in my desired order?
The output of such snippet is
[0;36mnotice: /Stage[main]/Mc/Package[mc]/ensure: ensure changed 'purged' to 'latest'[0m
[1;35merr: /Stage[main]/Zendserverce/Package[zend-server-ce-php-5.2]/ensure: change from purged to latest failed: Could not update: Execution of '/usr/bin/apt-get -q -y -o DPkg::Options::=--force-confold install zend-server-ce-php-5.2' returned 100: Reading package lists...
Building dependency tree...
Reading state information...
E: Couldn't find package zend-server-ce-php-5.2 at /tmp/vagrant-puppet/modules 0/zendserverce/manifests/init.pp:28[0m
[0;36mnotice: /Stage[main]/Zendserverce/Exec[wget http://repos.zend.com/zend.key -O- |apt-key add -]/returns: executed successfully[0m
[0;36mnotice: /Stage[main]/Zendserverce/File_line[debian_package]/ensure: created[0m
[0;36mnotice: Finished catalog run in 6.75 seconds[0m
So it says: Couldn't find package zend-server-ce-php-5.2
Can anyone guide me what is wrong?

Since Puppet 2.6.0 a new feature "relationship syntax" was introduced.
An example in Puppet 2.6.0 and above would look like this:
exec { "apt-update":
command => "/usr/bin/apt-get update"
}
Exec["apt-update"] -> Package <| |>
Every time a package command is executed, the dependency (in our case 'apt-update') will be triggered fist.
You can even define longer chains.

You need to specify the dependency relationships. The easiest/cleanest approach is to use the require parameter which is available for all resource types.
package { "zend-server-ce-php-5.2":
ensure => latest,
require => Exec['apt-get update'],
}
etc..

I tried previous variant but it doesn't work for me on Ubuntu 10.04
Finaly I prepared the following script, that runs update everytime the repository is older than one week:
exec { 'apt-get update':
command => "/usr/bin/apt-get update",
onlyif => "/bin/bash -c 'exit $(( $(( $(date +%s) - $(stat -c %Y /var/lib/apt/lists/$( ls /var/lib/apt/lists/ -tr1|tail -1 )) )) <= 604800 ))'"
}
Hope it helps.

I prefer to put apt-upgrade into a separate stage running before the main stage, so I don't have to hard-wire any dependencies. Check here: http://docs.puppetlabs.com/puppet/2.7/reference/lang_run_stages.html.
A simple example would look like below. It implies you have a separate class for doing the actual apt-update:
stage { "init": before => Stage["main"] }
class {"apt-update":
stage => init,
apt_mirror => $apt_mirror
}
Check my sample LAMPP-box on github to see how the pieces fit together: https://github.com/joerx/vagrant-lampp
Note: be careful with apt-upgrade, as some base boxes break by things like kernel upgrades.

In Puppet 3 this can be done by realizing virtual resources using resource collectors
# so you don't have to fully qualify paths to binaries
Exec { path => ['/usr/bin'] }
# virtual resource
#exec { 'sudo apt-get update':
tag => foo_update
}
# realize resource. filter by arbitrary "foo_update"
# tag and relate it to all Package resources
Exec <| tag == foo_update |> -> Package <| |>

Adding this snippet of voodoo worked for us:
Apt::Pin <| |> -> Package <| |>
Apt::Source <| |> -> Package <| |>
This forced an update. YMMV.

Package that needs updating APT lists should require Class['apt::update']
package { "zend-server-ce-php-5.2":
ensure => "latest",
require => Class['apt::update']
}
If you're using custom APT source, just ensure correct ordering:
Apt::Source['my_source']
-> Class['apt::update']

You should really be using the apt module to create sources and add keys: https://forge.puppet.com/puppetlabs/apt
If you're using hiera:
apt::sources:
'artifactory-pro-debs':
location: 'http://repos.zend.com/zend-server/deb'
release: 'server
repos: 'non-free'
key:
source: 'http://repos.zend.com/zend.key'

Related

How to check if package is installed by using unless?

I've created a puppet script to install Azure client and in the last step before using yum install, I want to make sure that the package haven't installed before for prevent from duplicate install.
My concept is
Execute the script if the output from az --help give nothing (which mean there's no Azure install)
or if you guys have any better choices please guide me, thanks!
And my code is
#install azure client
exec { 'install-azure':
command => '/bin/yum install azure-cli -y',
path => '/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:',
unless => 'az --help',
#require => Exec['yumrepolist']
}
It seems like there're something wrong with the code, I've checked a particular agent by using
puppet agent -t
Notice:
/Stage[main]/Os_preparation::Azure_install/Exec[yumrepolist]/returns:
executed successfully Error:
/Stage[main]/Os_preparation::Azure_install/Exec[install-azure]: Could
not evaluate: Could not find command 'az'
Any ideas? Thanks
You should install azure-cli using a package resource. Also, you should add its Yum repository as a yumrepo resource.
Try something like the following, which replicates the instructions on https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-yum?view=azure-cli-latest.
yumrepo { 'azure-cli':
descr => 'Azure CLI',
baseurl => 'https://packages.microsoft.com/yumrepos/azure-cli',
enabled => 1,
gpgcheck => 1,
gpgkey => 'https://packages.microsoft.com/keys/microsoft.asc',
}
package { 'azure-cli':
ensure => installed,
require => Yumrepo['azure-cli'],
}

puppet script for ibm websphere mq

Just started learning puppet and gone through some modules in forge,puppetlabs.com. Is there a module available to install IBM Websphere MQ.
Here are the steps I followed to install IBM Websphere MQ using Puppet.
Prerequisite:
Install steps
1. gunzip the file
2. untar the file to temp directory
3. ensure rpm package is installed
4. Accept license
5. Run the RPMs
6. Set up installation as primary.
Step1:
exec { 'gunzip_ibmmq':
unless => "test -f ${ibmwebspheremq::ibmmq_install_temp}/${ibmwebspheremq::ibmmq_archive_tar}",
cwd => "${ibmwebspheremq::ibmmq_install_temp}",
path => [ "/usr/bin", "/bin", "/usr/sbin", "/usr/local/bin", "/sbin" ] ,
command => "gunzip ${ibmwebspheremq::ibmmq_install_temp}/${ibmwebspheremq::ibmmq_archive_gz}",
logoutput => true,
}
Step2:
exec { 'untar_ibmmq':
cwd => "${ibmwebspheremq::ibmmq_install_temp}",
path => [ "/usr/bin", "/bin", "/usr/sbin", "/usr/local/bin", "/sbin" ] ,
command => "tar -xvf ${ibmwebspheremq::ibmmq_install_temp}/${ibmwebspheremq::ibmmq_archive_tar}",
logoutput => true,
}
Step3:
$admin_packages = ['rpm']
# Ensure required Package is installed
package { $admin_packages:
ensure => 'installed',
}
Step4:
Accept license
exec { 'acceptlicense_ibmmq':
cwd => "${ibmwebspheremq::ibmmq_install_temp}/server",
path => [ "/usr/bin", "/bin", "/usr/sbin", "/usr/local/bin", "/sbin" ] ,
command => "${ibmwebspheremq::ibmmq_install_temp}/server/mqlicense.sh -accept",
#creates => "${ibmwebspheremq::ibmmq_install_rpm}",
logoutput => true,
}
Step5:
exec { 'install_ibmmq':
cwd => "${ibmwebspheremq::ibmmq_install_temp}/server",
path => [ "/usr/bin", "/bin", "/usr/sbin", "/usr/local/bin", "/sbin" ] ,
command => "rpm --prefix ${ibmwebspheremq::ibmmq_install_root} -ivh ${ibmwebspheremq::ibmmq_install_temp}/server/MQSeries*.rpm",
#command => "rpm -ivh MQSeries*.rpm",
logoutput => true,
}
Questions I have now since I figured out the process.
Accept license steps from IBM is interactive, it forces you to enter 1 , how to you handle this in puppet so install can continue. Could not progress to next step bypassing this unless we manually accept the license. Is there a workaround to continue installing without this step and automate.
Is there a puppet module to install IBM JDK.
Step5: The way I installed RPMs is by running everything in a single command. (MQSeries*.rpm). Is it required to run one module at a time and in a particular order. Can this run in any order.
Thank you
I know it is a pretty old question, but you can now use the mq_install module for installation. and the mq_config when configuring you MQ environment with puppet.
Answers to two of your numbered questions:
You can accept the license using mqlicense.sh -accept as you did in the example, the response is Agreement accepted: Proceed with install.. This does not prompt for any response. This is documented in the IBM Knowledge Center under the Installing an IBM MQ client on Linux topic.
If want to accept the license without it being displayed, you can run the mqlicense.sh script with the -accept option.
./mqlicense.sh -accept
You must accept the license agreement before you can proceed with the installation.
You can specify all the rpms you require in a single rpm command or using a wildcard as you have in the example above as long as you are not missing any prerequisite rpms.

Running a command once after a group of packages is installed

I have an existing puppet manifest which installs a bunch of php5 packages and only after being installed restarts apache. The simplified manifest is something like
package { 'apache-php':
name => $modules,
ensure => installed
}
exec {'enable-mod-php':
command => $enable_cmd,
refreshonly => true
}
Package['apache-php'] ~> Exec['enable-mod-php'] ~> Service['apache']
After a system upgrade catalog runs have started failing with the following error message:
Error: Failed to apply catalog: Parameter name failed on Package[apache-php]: Name must be a String not Array at /etc/puppet/modules/apache/manifests/php.pp:22
I found out that I was using an undocumented feature/bug: Puppet 3.4.0 name as an array in package.
However, I'm having a hard time finding out how to redo my setup after the upgrade. How can I rewrite this manifest so that it works with more recent puppet versions?
Instead of using an arbitrary title for the package define in your example. (eg. apache-php) and using a name parameter, you can do the following:
$modules = ['foo','bar','baz']
package { $modules:
ensure => present
notify => Exec['enable-mod-php']
}
exec {'enable-mod-php':
command => $enable_cmd,
refreshonly => true,
notify => Service['apache']
}
service { 'apache':
# your apache params
}
I haven't looked at the code for the package provider, but can verify that the above works. You should also note that chaining arrows are all well and good, but according to the Puppet style guide, metaparameters are preferred.
Hope this helps.

How can i use puppet to install network tool like iptraf

i am using the example of iptraf on github
I do a git clone, and then sudo puppet apply init.pp
but i dont see iptraf installed on the ubuntu 11.04 host
now this puppet is a client ONLY instance, and NO Master.
from another example i see i can install apache2 as:
class basic_services {
##Get Apache
package { 'apache2':
ensure => 'installed',
}
##Edit the Apache Conf
file { "/etc/apache2/sites-available/default":
require => Package["apache2"],
owner => "root",
group => "root",
content => "$some_variables::apache_config",
}
##Make sure Apache is running, and restarts on changes to conf
service {'apache2':
require => Package["apache2"],
ensure => running,
subscribe => File["/etc/apache2/sites-available/default"],
}
}
so for iptraf:
init.pp
class iptraf {
include iptraf::base
}
base.pp
class iptraf::base {
package{'iptraf': ensure => installed }
}
I will use this example as a base to develop a manifest for Testing Tools
So what am i missing here , as after i run :
sudo puppet apply init.pp , and try to access iptraf, i get the message:
iptraf
The program 'iptraf' is currently not installed. You can install it by typing:
sudo apt-get install iptraf
in the directory:
/etc/puppet/modules/iptraf
- create a file:
iptraf.pp
- with contents:
package { "iptraf":
ensure => "installed"
}
- issue the command:
puppet apply iptraf.pp
/Stage[main]//Package[iptraf]/ensure: ensure changed 'purged' to 'present'
Finished catalog run in 2.71 seconds
run iptraf on command line , the UI POPS UP.
Done!
move the iptraf directory to the modules. Your directory structure should be this :
/etc/puppet/modules/iptraf/manifests/{init.pp,base.pp}
then do,
sudo puppet apply -e 'include iptraf'
that should install iptraf.
sudo iptraf should open a nice screen in your terminal :)

Augeas support on my Vagrant machine?

I'm trying to getting support for augeas on my Vagrant machine.
I tried to install some package with these directives:
package { "augeas-tools": ensure => installed }
package { "libaugeas-dev": ensure => installed }
package { "libaugeas-ruby": ensure => installed }
When i try to use augeas on my manifests, after the vm boot i receive this error:
err: Could not find a suitable provider for augeas
I'm using the precise32 official box with Vagrant 1.0.3.
Vagrant 1.0.3 has ruby 1.8.7 and puppet 2.7.14
$ ruby -v
$ ruby 1.8.7 (2011-06-30 patchlevel 352) [i686-linux]
$ puppet help
$ Puppet v2.7.14
This is my little manifest with php class, included after apache class, mysql and other classes tested separately.
All things works correctly excepting for the augeas command.
class php {
exec { "apt-update":
command => "/usr/bin/apt-get update",
refreshonly => true;
}
package { "augeas-tools": ensure => installed }
package { "libaugeas-dev": ensure => installed }
package { "libaugeas-ruby": ensure => installed }
package { "php5": ensure => installed }
package { "php5-cli": ensure => installed }
package { "php5-xdebug": ensure => installed }
package { "php5-curl": ensure => installed }
package { "php5-intl": ensure => installed }
package { "php5-imap": ensure => installed }
package { "php5-mcrypt": ensure => installed }
package { "php5-imagick": ensure => installed }
package { "php5-sqlite": ensure => installed }
package { "php5-gd": ensure => installed }
package { "php-apc": ensure => installed }
package {
"libapache2-mod-php5" :
ensure => installed,
require => Package["php5"]
}
augeas { "php-cli":
require => [
Package["php5"],
Package["augeas-tools"],
Package["libaugeas-dev"],
Package["libaugeas-ruby"],
],
context => "/etc/php5/cli/php.ini",
changes => [
"set date.timezone Europe/Rome",
"set short_open_tag Off",
];
}
augeas { "php-apache":
require => [
Package["php5"],
Package["augeas-tools"],
Package["libaugeas-dev"],
Package["libaugeas-ruby"],
],
context => "/etc/php5/apache2/php.ini",
changes => [
"set date.timezone Europe/Rome",
"set short_open_tag Off",
];
}
}
After installation of packages, logging in the vagrant machine with "vagrant ssh", i launch:
vagrant#precise32:~$ ruby -raugeas -e "puts Augeas.open"
#<Augeas:0xb77a3598>
Thanks in advance!
I added the following to my Vagrantfile and it augeas started working.
Before declaring puppet provisioner add the following line, if on ubuntu:
config.vm.provision :shell, :inline => "sudo apt-get update && sudo apt-get install puppet -y"
This will update your apt packages and then update puppet client whose latest version already has a fix.
It turns out that this wasn't fixed in bug #6907 that I referenced in my other answer. That fix only worked for Puppet providers that depended on commands that were then supplied during the run.
For the Augeas provider, it uses an internal Puppet called "features" to check if the ruby-augeas library is available or not. Features are only being checked once and the results cached, so even after installing the library, this meant the feature still evaluated to false.
I filed this upstream as bug #14822 and have sent a pull request with a fix. Testing with the patch, I now get this successful run:
notice: /Stage[main]//Package[ruby-augeas]/ensure: created
notice: /Stage[main]//Augeas[test]/returns: executed successfully
I'm not familiar with Vagrant, but I think you'll need to find a workaround to install the libaugeas-ruby package before the Puppet run in the meantime.
On Puppet 2.7.14, this should work as the dependencies for providers will only be evaluated when they're needed - i.e. when Puppet needs to run those Augeas resources.
Without the full Puppet log file to confirm, I suspect that it's because you're missing explicit dependencies between the Augeas package(s) and the Augeas resources that need them. Remember, listing the resources in the manifest in that order doesn't mean Puppet executes it that way.
You could either add requires parameters to every Augeas resource:
augeas { "php-cli":
require => [ Package["php5"], Package["libaugeas-ruby"] ],
# ...
}
Or use the chaining syntax to automatically make every Augeas resource depend on a package. Add this on a line inside the class, but not inside any resource:
Package["libaugeas-ruby"] -> Augeas <| |>
After reading answer from #m0dlx I inspect /home/vagrant/postinstall.sh file and found that Vagrant uses own copy of Ruby:
# The base path to the Ruby used for the Chef and Puppet gems ruby_home="/opt/vagrant_ruby"
After that I find file augeas.rb at /opt/vagrant_ruby/lib/ruby/gems/1.8/gems/puppet-2.7.19/lib/puppet/provider/augeas/augeas.rb and edit it, by changing line
confine :true => Puppet.features.augeas?
to
confine :true => :augeas
(Shortly speaking I partially apply patch from #m0dlx.)
After that this error is gone.

Resources