Thursday, August 21, 2014

Playing with puppet vol II - module

In the previous post I have installed puppet using master/agent architecture. Today I'm not expecting puppet to do more work. I want it to do the same job but witch much better way. And that's what modules are for.

TOC

Module creation

I'll create a new puppet module named vajko-basic. Name is comprised of two components. Module creator (vajko) and module name (basic). This module will contain all puppet resources (which is only user test resource). At first I'll generate empty puppet module:

[root@puppet ~]# puppet module generate vajko-basic
We need to create a metadata.json file for this module.  Please answer the
following questions; if the question is not applicable to this module, feel free
to leave it blank.

Puppet uses Semantic Versioning (semver.org) to version modules.
What version is this module?  [0.1.0]
-->

Who wrote this module?  [vajko]
-->

What license does this module code fall under?  [Apache 2.0]
-->

How would you describe this module in a single sentence?
--> Module for setting up server as I like it

Where is this module's source code repository?
-->

Where can others go to learn more about this module?
-->

Where can others go to file issues about this module?
-->

----------------------------------------
{
  "name": "vajko-basic",
  "version": "0.1.0",
  "author": "vajko",
  "summary": "Module for setting up server as I like it",
  "license": "Apache 2.0",
  "source": "",  
  "project_page": null,
  "issues_url": null,
  "dependencies": [
    {
      "name": "puppetlabs-stdlib",
      "version_range": ">= 1.0.0"
    }
  ]
}
----------------------------------------

About to generate this metadata; continue? [n/Y]
--> y

Notice: Generating module at /root/vajko-basic...
Notice: Populating ERB templates...
Finished; module generated in vajko-basic.
vajko-basic/Rakefile
vajko-basic/manifests
vajko-basic/manifests/init.pp
vajko-basic/spec 
vajko-basic/spec/classes
vajko-basic/spec/classes/init_spec.rb
vajko-basic/spec/spec_helper.rb
vajko-basic/tests
vajko-basic/tests/init.pp
vajko-basic/README.md
vajko-basic/metadata.json

Currently this module does nothing. There is defined empty class named basic and a lot of comments in /root/vajko-basic/manifest/init.pp:

[root@puppet ~]# pwd
/root
[root@puppet ~]# cat vajko-basic/manifests/init.pp 
# == Class: basic
#
# Full description of class basic here.
#
# === Parameters
#
# Document parameters here.
#
# [*sample_parameter*]
#   Explanation of what this parameter affects and what it defaults to.
#   e.g. "Specify one or more upstream ntp servers as an array."
#
# === Variables
#
# Here you should define a list of variables that this module would require.
#
# [*sample_variable*]
#   Explanation of how this variable affects the funtion of this class and if
#   it has a default. e.g. "The parameter enc_ntp_servers must be set by the
#   External Node Classifier as a comma separated list of hostnames." (Note,
#   global variables should be avoided in favor of class parameters as
#   of Puppet 2.6.)
#
# === Examples
#
#  class { basic:
#    servers => [ 'pool.ntp.org', 'ntp.local.company.com' ],
#  }
#
# === Authors
#
# Author Name 
#
# === Copyright
#
# Copyright 2014 Your name here, unless otherwise noted.
#
class basic {


}

I'll try to build and install the module:

[root@puppet ~]# puppet module build vajko-basic/
Notice: Building /root/vajko-basic for release
Module built: /root/vajko-basic/pkg/vajko-basic-0.1.0.tar.gz
[root@puppet ~]# puppet module install /root/vajko-basic/pkg/vajko-basic-0.1.0.tar.gz 
Notice: Preparing to install into /etc/puppet/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Notice: Installing -- do not interrupt ...
/etc/puppet/modules
\-+ vajko-basic (v0.1.0)
  \-- puppetlabs-stdlib (v4.3.2)

Notice it will also install dependant module puppetlabs-stdlib. I will list all modules just to check:

[root@puppet ~]# puppet module list
Warning: Missing dependency 'puppetlabs-stdlib':
  'vajko-basic' (v0.1.0) requires 'puppetlabs-stdlib' (>= 0.0.0)
/etc/puppet/modules
|-- puppetlabs-stdlib (v4.3.2)
\-- vajko-basic (v0.1.0)
/usr/share/puppet/modules (no modules installed)

There is a warning telling me that module vajko-basic requires module puppetlabs-libs. But this module has already been installed. It is a bug. Fix is quite easy - replace '-' with '/' in requirements part of module metadata:

[root@puppet ~]# sed -i -e 's|puppetlabs-stdlib|puppetlabs/stdlib|' vajko-basic/metadata.json 

I need to rebuild and reinstall the module. But there is another bug hidden in the uninstallation process:

[root@puppet7 ~]$ puppet module uninstall vajko-basic
Notice: Preparing to uninstall 'vajko-basic' ...
Error: Could not uninstall module 'vajko-basic' (v0.1.0)
  Installed module has had changes made locally
    Use `puppet module uninstall --force` to uninstall this module anyway

Puppet thinks that some changes where made to installed module and therefore he refused to uninstall it. I'll check the changes:

[root@puppet7 ~]$ puppet module changes /etc/puppet/modules/basic/
Warning: 1 files modified
metadata.json

There are some changes in the metadata file:

[root@puppet7 ~]$ diff /etc/puppet/modules/basic/metadata.json /root/vajko-basic/metadata.json 
12c12
<       "name": "puppetlabs-stdlib",
---
>       "name": "puppetlabs/stdlib",
16a17
> 

Name was changed by me, but the other change id weird. There is missing newline at the end of the file /etc/puppet/modules/vajko-basic/metadata.json. It must have lost during module building or installation. This bug has been fixed in the master, but I have to fix it here. I will manually remove newline from the end of the /root/vajko-basic/metadata.json. Then I will uninstall, rebuild and install the module:

[root@puppet ~]# puppet module uninstall --force vajko-basic
Notice: Preparing to uninstall 'vajko-basic' ...
Removed 'vajko-basic' (v0.1.0) from /etc/puppet/modules
[root@puppet ~]# puppet module build /root/vajko-basic
Notice: Building /root/vajko-basic for release
Module built: /root/vajko-basic/pkg/vajko-basic-0.1.0.tar.gz
[root@puppet ~]# puppet module install /root/vajko-basic/pkg/vajko-basic-0.1.0.tar.gz 
Notice: Preparing to install into /etc/puppet/modules ...
Notice: Downloading from https://forgeapi.puppetlabs.com ...
Notice: Installing -- do not interrupt ...
/etc/puppet/modules
\-+ vajko-basic (v0.1.0)
  \-- puppetlabs-stdlib (v4.3.2)

I'll check if module list won't throw the warning:

[root@puppet ~]# puppet module list
/etc/puppet/modules
|-- puppetlabs-stdlib (v4.3.2)
\-- vajko-basic (v0.1.0)
/usr/share/puppet/modules (no modules installed)

And if there are changes or not:

[root@puppet ~]# puppet module changes /etc/puppet/modules/basic/checksums.json 
Notice: No modified files

Site manifest

Module is finally in good condition so I can define resources there. At first I'll put there user resource from site manifest:

[root@puppet ~]# cat /root/vajko-basic/manifests/init.pp 
class basic {

    user { 'test':
        ensure => 'absent',
        home => '/home/test',
        managehome => true,
        uid => 5555,
        gid => 52,
        password => '$6$RjjYOArA$DqJfCY81QtNpYvlHHxMTDIuvXtIVwznRRH3ww2HU4NWU.GJ2SgJiOOnDh8DSPsPOB.JiyRM2a9sKzaYOb5K3f0',
    }
}

Notice that I changed the property ensure from 'present' to 'absent'. User test exists on the puppet client:

[root@puppet7 ~]$ id test
uid=5555(test) gid=52(puppet) groups=52(puppet)

When this module will be applied on the client, puppet will remove the user. Currently I have installed previous version of the module (without user resource). Therefore I have to rebuild and reinstall it:

[root@puppet ~]# puppet module uninstall vajko-basic
[root@puppet ~]# puppet module build vajko-basic
[root@puppet ~]# puppet module install /root/vajko-basic/pkg/vajko-basic-0.1.0.tar.gz 

I need to tell puppet to apply basic module (class) to puppet7 client. That should be defined in the site manifest. Here's new content:

[root@puppet ~]# cat /etc/puppet/manifests/site.pp
    node 'puppet7.localdomain' {
        include basic
    }

Wait a few minutes (or force catalog refresh with puppet agent -t on puppet7) and this appears in the log:

[root@puppet7 ~]$ systemctl status puppet
.
.
.
Aug 21 14:09:06 puppet7.localdomain userdel[2347]: delete user 'test'
Aug 21 14:09:07 puppet7.localdomain puppet-agent[1831]: (/Stage[main]/Basic/User[test]/ensure) removed
Aug 21 14:09:07 puppet7.localdomain puppet-agent[1831]: Finished catalog run in 0.17 seconds

User test is gone:

[root@puppet7 ~]$ id test
id: test: no such user

Sources

No comments:

Post a Comment