Breaking old practices

When Puppet Labs decided to work on the parser and on the new features, they also decided to remove some features that had already been deprecated for a couple of releases.

Converting node inheritance

Node inheritance has been considered good practice during older Puppet releases. To avoid too much code on the node level, a generic, nonexistent host was created (basenode) and the real nodes inherited from basenode:

node basenode {
  include security
  include ldap
  include base
}
node 'www01.example.net' inherits 'basenode' {
  class { 'apache': }
  include apache::mod::php
  include webapplication
}

This node classification is no longer supported by Puppet 4.

As of 2012, the Roles and Profiles pattern became increasingly popular, bringing new methods on how to allow smart node classification. From a technical point of view, roles and profiles are Puppet classes. The profile module wraps technical modules and adapts their usage to the existing infrastructure by providing data such as ntp servers and ssh configuration options. The role module describes system business use cases and makes use of the declared profiles:

class profile::base {
  include security
  include ldap
  include base
}
class profile::webserver {
  class { 'apache': }
  include apache_mod_php
}

class role::webapplication {
  include profile::base
  include profile::webserver
  include profile::webapplication
}

node 'www01.example.net' {
  include role::webapplication
}

Tip

The final chapter will describe the Roles and Profiles pattern in some more detail.

Dealing with bool algebra on Strings

A minor change with a huge impact is the change of empty string comparison. Prior to Puppet 4, one could test for either an unset variable or a variable containing an empty string by checking for the variable:

class ssh (
  $server = true,
){
  if $server {...}
}

The ssh class behaved similar ($server evaluates to true) when used within the following different declarations:

include ssh
class { 'ssh': server => 'yes', }

Disabling the server section in the ssh class could be achieved by the following class declarations:

class { 'ssh': server => false, }
class { 'ssh': server => '', }

The behavior of the last example (empty string) changed in Puppet 4. The empty string now equals a true value in Boolean context just as in Ruby. If your code makes use of this way of variable checking, you need to add the check for empty string to retain the same behavior with Puppet 4:

class ssh (
  $server = true,
){
  if $server and $server != '' {...}
}

Using strict variable naming

Variables sometimes look like constants and exhibit the following features:

  • Variables cannot be declared again
  • In the scope of one node, most variables are static (hostname, fqdn, and so on)

Sometimes developers prefer to write the variables in capital letters due to the previously mentioned items, to make them look like Ruby constants.

With Puppet 4, variable names must not start with a capital letter:

class variables
{
  $Local_var = 'capital variable'
  notify { "Local capital var: ${Local_var}": }
}

Declaring this class will now produce the following error message:

root@puppetmaster:/etc/puppetlabs/code/environments/production/modules# puppet apply -e 'include variables'
Error: Illegal variable name, The given name 'Local_var' does not conform to the naming rule /^((::)?[a-z]w*)*((::)?[a-z_]w*)$/ at /etc/puppetlabs/code/environments/production/modules/variables/manifests/init.pp:3:3 on node puppetmaster.example.net

Learning the new reference syntax

Due to the type system and due to the reason that Puppet 4 now takes everything as an expression, one has to name references on other declared resources properly. References now have some strict regulations:

  • No whitespace between reference type and opening bracket
  • The reference title (used without quotes) must not be spelled with a capital letter

The following will produce errors on Puppet 4:

User [Root]
User[Root]

Starting with Puppet 4, references have to be written in the following pattern:

Type['title']

Our example needs to be changed to:

User['root']

Cleaning hyphens in names

Many modules (even on the module Forge) have used the hyphen in the module name. The hyphen is now no longer a string character, but a mathematical operator (subtraction). In consequence, hyphens are now strictly forbidden in the following descriptors:

  • The module name
  • Any class name
  • Names of defined types

When using modules with hyphens, the hyphen needs to be removed or replaced with a string character (for example, the underscore).

This is possible with older versions as follows:

class syslog-ng {...}

include syslog-ng

Now, the new style is as follows:

class syslog_ng {
  ...
}

include syslog_ng

No Ruby DSL anymore

Some people used the possibility to put .rb files as manifests inside modules. These .rb files contained Ruby code and were mostly needed for working with data. Puppet 4 now has data types that make this obsolete.

The support for these Ruby manifests has been removed in Puppet 4.

Relative class name resolution

With Puppet 3 and older, it was required to specify absolute class names in case that a local class name was identical to another module:

# in module "mysql"
class mysql {
  ...
}
# in module "application"
class application::mysql {
  include mysql
}

Within the scope of the application:: namespace, Puppet 3 would search this namespace for a mysql class to be included. Effectively, the application::mysql class would include itself. But this was not what we intended to do. We were looking for the mysql module instead. As a workaround, everybody was encouraged to specify the absolute path to the mysql module class:

class application::mysql {
  include ::mysql
}

This relative name resolution no longer applies in Puppet 4. The original example works now.

Dealing with different data types

Due to the reason that Puppet 3 was not aware of the different data types (mostly everything was dealt with as being of type string) it was possible to combine several different data types.

Puppet 4 now is very strict when it comes to combining different data types. The easiest example is dealing with float and integer; when adding a float and an integer, the result will be of type float.

Combining actions on different data types such as string and bool will now result in an error.

The following code will work:

case $::operatingsystemmajrelease {
  '8': {
    include base::debian::jessie
  }
}

On the other hand, the following code will not work:

if $::operatingsystemmajrelease > 7 {
  include base::debian::jessie
}

You will receive the following error message:

Error: Evaluation Error: Comparison of: String > Integer, is not possible. Caused by 'A String is not comparable to a non String'

Review comparison of different Facter variables carefully. Some Facter variables such as operatingsystemmajrelease return data of the type string, whereas processorcount returns an integer value.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset