How to split puppet files - puppet

Just wondering if I have the following puppet file and I would like to split them into separate files. Do I have to create module? Can't I just include them?
node default {
include mysql
}
class mysql {
# Make sure MySQL is ...
notify {"Mysql":}
# installed
package { 'mysql':
require => Exec['apt-update'], # require 'apt-update' before installing
ensure => installed,
}
# and running
service { 'mysql':
ensure => running,
enable => true,
}
}
...
I just want to take out mysql class to be on separate file. How to do this simple thing? Btw I'm using masterless puppet
Edit
Big big apologies, the truth is I was only using puppet without vagrant. But since I'm not a devops expert, when there was a revision on my question to include vagrant I just accepted it. Sorry for the confusion and let me revise my question
Can I do the separation WITHOUT vagrant? If I have to so be it.
Thanks

You can move your mysql class into its own module
you'll end up with something like this
.
├── Vagrantfile
├── puppet
| ├── manifests
| ├──── base.pp
| └── modules
| └── mysql
| └── manifests
| └──── init.pp
Vagrantfile would be like
Vagrant.configure("2") do |config|
<make all your configuration here>
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "puppet/manifests"
puppet.manifest_file = "base.pp"
puppet.module_path = "puppet/modules"
end
end
end
the base.pp file will only contain
node default {
include mysql
}
and your mysql/init.pp file will contain the mysql class itself
class mysql {
# Make sure MySQL is ...
notify {"Mysql":}
# installed
package { 'mysql':
require => Exec['apt-update'], # require 'apt-update' before installing
ensure => installed,
}
# and running
service { 'mysql':
ensure => running,
enable => true,
}
}
It can be a good idea for module exercise in puppet, but honestly you're more likely to use an existing module and not reinvent the wheel: https://forge.puppet.com/puppetlabs/mysql/2.2.3 will be a good module to use

Related

Can not find class during Puppet apply

My puppet structure is as follows
/puppet
/manifests
/nodes
redis.pp
site.pp
/modules
The site.pp resembles
class base {
include ml-basefw
include ml-users
include ml-filelimits
include repoforge
include epel
class { 'ml-yumrepo':
base_url => "http://${puppet_server}/yumrepo"
}
}
import 'nodes/*.pp'
node default {
include base
}
When I run
puppet apply --modulepath=/puppet/modules:/puppet/manifests --noop --debug /puppet/manifests/nodes/redis.pp
I receive
Error: Could not find class base for redis-1.test.ml.com on node redis-1.test.ml.com
Is there something non-standard about my file layout that precludes me from using apply?
I am not the maintainer of the puppet module so I am not able to alter the file structure or layout.
There are numerous related questions but I wasn't able to relate them to the problem that I am having.
Edit1 : Adding redis.pp
node /^redis-\d+(.stage)?(.test)?(.aws)?.ml.com$/ {
include base
include epel
class { 'redis':
package_ensure => '2.8.15-1.el6.remi',
service_ensure => 'running',
conf_bind => '0.0.0.0',
conf_port => '6379',
}
firewall { '176 allow port 6379 for redis traffic':
chain => 'INPUT',
state => ['NEW'],
dport => '6379',
proto => 'tcp',
action => 'accept'
}
}
What happens when you run puppet apply against your site.pp file instead? You probably don't have a node definition in your redis.pp file (nor should you).
This does in fact look a little messy and convoluted.
What you want is
an actual base module
defining class base in /puppet/modules/base/manifests/init.pp
You should also loose the import statement by arranging your manifests better. If your version of Puppet is recent enough (I think 3.6+), just see the docs.
fist of all, puppet have the entry manifest file.
in master mode, the entry is site.pp and puppet deprated deprecated it from version 3.5, it started auto imported all manifest files in specified directory.
in apply mode, the entry is specified file in your command.
so it works fine in your production environment, puppet master read site.pp(contains class base) and import nodes/*.pp(redis.pp, contains node definition). but when you use "puppet apply /puppet/manifests/nodes/redis.pp", puppet just read redis.pp, no anyone tell puppet where the base class is.

Puppet Could not find dependency Class

I am trying to pull things out into roles and profiles and am having an issue. I am using puppet apply for all of this as I am using it to finish setting up my Puppet Master. If I define my node in site.pp as shown here:
[root#puppet puppetdbsetup]# cat manifests/site.pp
node 'puppet' {
include ::roles::puppetmaster
}
I get this error:
[root#puppet puppetdbsetup]# puppet apply manifests/site.pp --environmentpath /etc/puppet/environments --environment puppetdbsetup --noop
Notice: Compiled catalog for puppet.belkin in environment puppetdbsetup in 1.29 seconds
Error: Could not find dependency Class[Puppet::Install] for File[/etc/puppet/hiera.yaml] at /etc/puppet/environments/puppetdbsetup/modules/p
uppet/manifests/master.pp:31
If I run puppetmaster.pp (shown below) with puppet apply directly it doesn't throw the same error.
[root#puppet puppetdbsetup]# cat modules/roles/manifests/puppetmaster.pp
class roles::puppetmaster {
#include profiles::base
include profiles::puppet::master
}
Can anyone tell me why this is and how to fix it? As a side note, all three modules referenced here are hand written... none are Forge modules.
Update 1
Here is my puppet::install class:
[root#puppet puppetdbsetup]# cat modules/puppet/manifests/install.pp
class puppet::install {
package { 'puppet':
ensure => present,
}
}
Somewhere in your manifest, you are declaring a File[/etc/puppet/hiera.yaml] that depends on Class[Puppet::Install], like
file { '/etc/puppet/hiera.yaml': require => Class['puppet::install'] }
or so
Class['puppet::install'] -> file { '/etc/puppet/hiera.yaml': ... }
or something in that vein.
What you are lacking is the actual declaration of the class either via
include puppet::install # nice!
or
class { 'puppet::install': } # please don't
If in doubt, add the include line near the file declaration. It is usually safe to include a class multiple times.
If you apply puppetmaster.pp directly, you're just defining the class not applying it.
You need to do puppet apply -e 'include ::roles::puppetmaster' to be comparible.
The other error is probably caused by modules/puppet/manifests/install.pp not existing, or the class definition in the file not starting with
class puppet::install (
....
....
) {

Puppet Apply: Could not find class for

It seems pretty simple thing, and it works on Vagrant, but I can't make it work on a EC2 server.
When:
puppet apply manifests/init.pp
Error:
Could not find class base for s1.ec2.internal at /var/lib/jenkins/jobs/s1/workspace/manifests/init.pp:1 on node s1.ec2.internal
File ./manifests/init.pp:
include base
File ./manifests/base.pp:
class base {
exec { "apt-get update":
command => "/usr/bin/apt-get update",
timeout => 0
}
package { ["vim", "git", "build-essential"]:
ensure => present,
require => Exec["apt-get update"]
}
}
Puppet v2.7.23
Like Felix stated the class base is being looked for in the modules of your puppet manifests. The directory structure of your modules as follows:
$confdir/
|- manifests
|- init.pp <- The file you reference to when executing puppet apply
|- modules
|- base
|- manifests
|- init.pp <- The file containing your base class
What Felix forgot to mention was that there needs to be another manifests directory within the base module directory.
See also https://docs.puppetlabs.com/puppet/latest/reference/modules_fundamentals.html
Usually class base will be found only in a module named base.
Try putting it into modules/base/init.pp instead of manifests/base.pp.
In my case it was a permissions issue - the files were owned by root but I wasn't running puppet with sudo

How can I improve class function using a template or other generic method

I have a class function that downloads packages using the package method in puppet.
class package {
define install( $dependence=File[$dummy_dependence_file])
{
package { $name:
ensure => "installed",
require => $dependence,
}
}
}
I currently use it in my init.pp like so
# install dependencies
$dependence_list = ['glibc.i686','wget','gcc']
#
# ==Actions
# Install glibc, gcc, wget dependency for running sybase
#
# ==Requires
# * http proxy to be setup to get around jpm proxy
package::install { $dependence_list:
dependence => File[ $http_setup_name ],
}
I would like this method to be more generic. Is it possible instead of using a array of dependencies, which I need to edit the init.pp each time. To use a template and read each dependency from a file? Or any other generic method would do...
An example would be great.
you should be able to simply set the requirement within the package and pass an array to the package too:
$my_packages = ['apache2', 'curl', 'wget']
$my_dependencies = [File['a'], File['b'], User['tester']]
package { $my_packages:
ensure => installed,
require => $my_dependencies,
}
Using this type of package should be sufficient for your needs.
However if you want to read the dependency list from a file you can use the 'template' function. ie.
$my_dependencies = template('modulepath/templates/dependency_list.erb')
Finally you're dependency_list.erb would look like this:
[File['a'], File['b'], User['tester']]
and that's all there really is to it!
For more information you can see http://docs.puppetlabs.com/guides/templating.html

Puppet breaks with multiple node inheritances

Puppet on the tst-01 works fine when using:
node "tst-01" inherits basenode {
But it breaks when I try to organize servers into groups with this configuration:
node "tst-01" inherits redhat6server {
The error with "inherits redhat6server" is:
err: Could not retrieve catalog; skipping run
[root#tst-01 ~]# puppet agent --test
err: Could not retrieve catalog from remote server: Error 400 on SERVER: Failed to parse template ldap/access.conf: Could not find value for 'netgroup' at 124:/etc/puppet/modules/ldap/templates/access.conf at /etc/puppet/modules/ldap/manifests/init.pp:82 on node tst-01.tst.it.test.com
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
This is the access.conf file, that works fine if inherits is set to "inherits basenode".
[root#puppet]# grep -v "#" /etc/puppet/modules/ldap/templates/access.conf
+ : root : LOCAL
+ : #<%= netgroup %> : ALL
- : ALL : ALL
[root#puppet]#
This is the configuration in /etc/puppet/manifests/nodes.pp.
# Basenode configuration
node "basenode" {
include resolv_conf
include sshd
include ntpd
include motd
}
# Groups
node "redhat6server" inherits basenode {
include ldap_auth
}
# Testservers
node "tst-01" inherits redhat6server {
$netgroup = tst-01
}
I am planning to bring more organisation (read: avoid configuration repetition) in the nodes.pp by grouping machines, e.g. RH5 and RH6 machines instead of adding multiple lines of includes for all RH5 and RH6 servers.
Your running into a variable scoping problem. The official documentation discusses this issue.
In short, redhat6server doesn't have access to the netgroup variable.
The method I employ to work around this is to use hiera. With this, the ldap_auth module can be defined this way, and it will pull the value from a hiera configuration file (typically a yaml file in /etc/puppet/hiera).
You would defined ldap_auth like this:
ldap_auth/manifests/init.pp:
class ldap_auth($netgroup=hiera('netgroup')) {
...
}
Or if your on puppet 3.x, you can use automatic parameter lookup:
class ldap_auth($netgroup) {
...
}
And have a yaml file with:
ldap_auth::netgroup = 'netgroup'

Resources