How to provide a startup service file in Puppet - puppet

We have RedHat 7.2 Linux OS and use puppet to perform our tasks. I am using puppet to install some software, which has worked fine and now the final step is to create an OS level service. In earlier versions of RHEL, we used chkconfig but that has been replaced with systemctl. Of course, the recommended way of performing this task is using a service. Since this is a custom software, I have my own startup script that I usually copy over to /etc/init.d, run chkconfig and then startup the service. How do I perform these tasks via Puppet for RedHat 7.2 OS ? I only want to create the service (not start it up or anything). This way, when the server reboots, the service will startup the app.
EDIT :
#redstonemercury for RHEL 7 I would think the following would be required. But your suggestion definitely helps as I was thinking along the same lines.
https://serverfault.com/questions/814611/puppet-generated-systemd-unit-files
file { '/lib/systemd/system/myservice.service':
mode => '0644',
owner => 'root',
group => 'root',
content => template('modulename/myservice.systemd.erb'),
}~>
exec { 'myservice-systemd-reload':
command => 'systemctl daemon-reload',
path => [ '/usr/bin', '/bin', '/usr/sbin' ],
refreshonly => true,
}

In puppet, use a package resource to install the package (assuming it's in repos that you're declaring already), then use a file resource to declare the /etc/init.d file, and put require => Package[<package_resource_name>] as a parameter in the file declaration to ensure the custom file gets created after the package has installed (so doesn't potentially get overwritten by the package's /etc/init.d file). E.g.:
package { 'mypackage':
ensure => present,
}
file { '/etc/init.d/mypackage':
ensure => present,
content => template('mypackage/myinitd'),
require => Package['mypackage'],
}
This is if you want to use a template. For a file, instead of content use source: source => puppet://modules/mypackage/myinitd

Related

Puppet exec a command before the package is installed

I am trying to run a power shell script just before the Pacakage starts installing an msi installer. The script cleans up certain un-managed resources that would block installer.
What I tried is,
file { 'c:\Test\cleanup.ps1.file' :
path => 'c:\Test\cleanup.ps1',
ensure => present,
source => 'puppet:///modules/test/cleanup.ps1',
source_permissions => ignore,
}
exec { 'c:\Test\cleanup.ps1.file':
refreshonly => true,
provider => powershell,
}
package { 'ServiceInstaller':
ensure => $version,
require => [Package['Service1Installer'],Exec['c:\Test\cleanup.ps1']],
}
But require attribute doesn't fire the command. Could someone please help me to achieve this behaviour.
There is this notify command, that would send a EXEC notification, but that happens after the installation. What I need is before the installation. Thanks in advance.
The trick to getting this working properly is that something has to write c:\Test\cleanup.ps1.file only when you need the script to be triggered to run, and the exec resource has to subscribe to it. Otherwise, if that file doesn't change, and the exec isn't subscribed, the exec resource does not think it needs to run so the puppet run completes but the script never fires.
Based on the code you pasted here, it looks like you're specifying $version in the class? And I'm guessing you're updating this either in the class or in hiera explicitly when you want to upgrade? If so, you could have the c:\Test\cleanup.ps1.file file write an inline template and just put the version number in that file. When you update the version in the class/hiera/wherever in puppet you're doing this, the file would update and the exec would kick off.
This would look something like:
file { 'c:\Test\cleanup.ps1.file' :
path => 'c:\Test\cleanup.ps1',
ensure => present,
content => inline_template("<%= #version %>"),
source_permissions => ignore,
}
exec { 'c:\Test\cleanup.ps1.file':
refreshonly => true,
provider => powershell,
subscribe => File['c:\Test\cleanup.ps1.file'],
}
package { 'ServiceInstaller':
ensure => $version,
require => [Package['Service1Installer'],Exec['c:\Test\cleanup.ps1']],
}
This is assuming you were just trying to use the cleanup.ps1.file as a trigger for the exec. If there is stuff in that file you need for other purposes, then leave that declaration as you had it, and make another file declaration as a trigger file with just the version in an inline template, and subscribe the exec to that one instead of the cleanup.ps1.file

Puppet: making .yaml dependent on .pp

I am trying to install docker onto a disk other than system on my CentOS 7.2 VM. I create a directory and a symlink first with the required target in my .pp, and then want to install docker using yaml.
file { '/data/docker-latest':
ensure => 'directory',
}
file { '/var/lib/docker-latest':
ensure => 'link',
target => '/data/docker-latest',
require => File['/data/docker-latest'],
}
For it to work, the directory and the symlink need to be created before the .yaml kicks in:
packages:
docker-latest:
ensure: installed
services:
docker-latest:
ensure: running
But there is no guarantee like this. Is there a way I can make my .yaml code to require => File['/var/lib/docker-latest']?
Or am I better off installing and running docker inside .pp?

Puppet reboot in stages

I need to do a two step installation of a CentOS6 host with puppet (currently using puppet apply) and got stuck. Not even sure it's currently possible today.
Step 1, setup of base system e.g. setup hosts, ntp, mail and some driver stuff.
reboot required
Step 2, setup of a custom service.
Can this bee done a smooth way? I'm not very familiar with the puppet environment yet.
First off, I very much doubt that any setup steps on a CentOS machine strictly require a reboot. It is usually sufficient to restart the right set of services to make all settings take effect.
Anyway, basic approach to this type of problem could be to
Define a custom fact that determines whether a machine is ready to receive the final configuration steps (Step 2 in your question)
Protect the pertinent parts of your manifest with an if condition that uses that fact value.
You may want to create a file first, then delete it when you are done installing the base system (ntp in the below example)
for example
exec { '/tmp/reboot':
path => "/usr/bin:/bin:/sbin",
command => 'touch /tmp/reboot',
onlyif => 'test ! -f /tmp/rebooted',
}
service { 'ntp':
require => Exec['/tmp/reboot'],
...
}
exec { 'reboot':
command => "mv /tmp/reboot /tmp/rebooted; reboot",
path => "/usr/bin:/bin:/sbin",
onlyif => "test -f /tmp/reboot",
require => Service['ntp'],
creates => '/tmp/rebooted',
}

Puppet User ID value and Package

I am trying to do the following using Puppet on an Ubuntu 10.04:
Copy a file that I have to a specific directory which will be owned by a specific user / group that does not exists yet since the package has not been installed
Install the package where it will not remove the directory and file that I created
To accomplish item #1, I basically tell Puppet to create a user and group first before copying the file. But the problem is that if I do not give a specific uid for Puppet, it will randomly pick a number like a number for user and not a number for system package.
So, how do I tell Puppet to choose a uid anything more than 1000?
If this is not possible, how do I tell Puppet not to start the package when it installs it. So I would just let Puppet install the package, but do not start the service, then copy my file, then I will start the service.
The user type has a parameter of system => which defaults to false, but can be set to true. This will generate the user with a UID below 500. Which seems to be what you want.
Ultimately what you'll want to do in my opinion is manage the config directory and the config via puppet as well.
This gives you the ability to do things like such:
package { foo: ensure => present }
file {
fooconfdir:
path => '/path/to/fooconfdir',
ensure => directory,
user => whatev,
group => alsowhatev,
require => Package[foo],
mode => morewhatev;
fooconf:
path => '/path/to/fooconfdir/fooconf',
ensure => present,
user => whatev,
content => template('whatev');
}
service { foo: ensure => running, enable => true, subscribe => File[fooconf] }
What that will do , is install your package then manage the config, then restart the service which will use your new config obviously on restart.

Puppet does not add my service to start up

I have this puppet module (monit) in which I declare monit service to be enabled (a.k.a to be started when the machine booted)
class monit {
$configdir = "/etc/monit.d"
package {
"monit": ensure => installed;
}
service { "monit":
ensure => running,
enable => true,
require => Package["monit"],
provider => init;
}
file {
'/etc/monit.d':
ensure => directory;
'/etc/monit.conf':
content => template('monit/monitrc.erb'),
mode => 0600,
group => root,
require => File['/etc/monit.d'],
before => Service[monit],
notify => Service[monit],
}
}
I then included with include monit inside default node.
However, when I apply this configuration, puppet is not setting monit as a start up service (use chkconfig --list monit just display 'off' and 'off')
However, if I run puppet apply -e 'service { "monit": enable => true, } ' then monit is added to start up properly.
Am I doing any thing wrong here? (Puppet 2.7.6)
The full configuration can be view at https://github.com/phuongnd08/Giasu-puppet
The issue is probably the provider => init line, which is overriding the default provider for handling services. The init provider is a very simple provider that doesn't support the "enableable" feature, so it can't set a service to start on boot.
See http://docs.puppetlabs.com/references/2.7.6/type.html#service for its capabilities.
In your puppet apply example, you don't specify the provider so it picks the most appropriate for your system - in your case the "redhat" provider that uses chkconfig.
To fix this, remove the provider line from your service {} definition and it will again default to the most appropriate. You only need to specify a provider if it picks incorrectly and then it's best to specify it as a global default.

Resources