Ask Your Question
0

puppet fails when using hiera lookup on package installation

asked 2018-03-20 15:06:59 -0500

andrew91 gravatar image

Hey guys. Pretty new to puppet and am having issues with a hiera lookup specifically when installing packages. I believe puppet thinks that the package resource is missing a title - it just has a variable as a title instead of the package name.

[root@canary production]# puppet agent -t

Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Evaluation Error: Missing title. The title expression resulted in undef at /etc/puppetlabs/code/environments/production/site/profiles/manifests/common/packages.pp:5:11 on node canary.esxi.com
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

If I run puppet apply packages.pp (changing it from a class to a normal manifest) it runs fine.

[root@puppet02 common]# vim /etc/puppetlabs/code/environments/production/site/profiles/manifests/common/packages.pp

$packages = lookup('packages::installed')

#class profiles::common::packages {

package { $packages:
    ensure => installed,
}

#}

As you can see "nmap" is now installed.

[root@puppet02 common]# puppet apply packages.pp
Notice: Compiled catalog for puppet02.esxi in environment production in 0.08 seconds
Notice: /Stage[main]/Main/Package[nmap]/ensure: created
Error: Execution of '/usr/bin/yum -d 0 -e 0 -y install wget'' returned 1: Error: Nothing to do
Error: /Stage[main]/Main/Package[wget']/ensure: change from purged to present failed: Execution of '/usr/bin/yum -d 0 -e 0 -y install wget'' returned 1: Error: Nothing to do
Notice: Applied catalog in 8.81 seconds

common.yaml (where the packages are listed):

[root@puppet02 common]# vim /etc/puppetlabs/code/environments/production/hieradata/common.yaml
packages::installed:
 - bash-completion
 - vim
 - nfs-utils
 - iotop
 - ntp
 - epel-release
 - deltarpm
 - mlocate
 - nmap
 - tcpdump
 - nethogs
 - sysstat
 - wget'
 - git
 - yum-utils
 - bind-utils
 - net-tools
 - yum-cron

I'm able to look up the "packages:installed"

[root@puppet02 common]# puppet lookup packages::installed
---
- bash-completion
- vim
- nfs-utils
- iotop
- ntp
- epel-release
- deltarpm
- mlocate
- nmap
- tcpdump
- nethogs
- sysstat
- wget'
- git
- yum-utils
- bind-utils
- net-tools
- yum-cron

[root@puppet02 common]# vim /etc/puppetlabs/code/environments/production/site/profiles/manifests/common/packages.pp

$packages = lookup('packages::installed')

class profiles::common::packages {

package { $packages:
    ensure => installed,
}

}

My site.pp file:

node default {
    contain roles::base
    #notify { "This is running the default in site.pp" }
}
edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
1

answered 2018-03-21 11:38:35 -0500

reidmv gravatar image

In general, it's not possible to set variables outside of class definitions / defined types / functions in Puppet code. The site.pp file is special, and is the only place where that typically works.

Right now, your profiles::common::packages class file tries to set a variable outside of the class block.

$packages = lookup('packages::installed')
class profiles::common::packages {
   ...
}

What you should do:

Give your profile class a class parameter.

class profiles::common::packages (
  $packages,
) {
  package { $packages:
      ensure => installed,
  }
}

Then, make use of automatic class parameter lookups from Hiera to provide a value for it.

The short version is

  • For a class named profiles::common::packages
  • With a parameter named packages
  • Puppet will _automatically_ try to look up profiles::common::packages::packages in Hiera to populate that parameter

There are other ways to do this if you want. For example, you could do an explicit lookup if you put the lookup inside your class code. E.g.

class profiles::common::packages {
  $packages = lookup('packages::installed')
   ...
}

Check out this recommendation though on data escalation path for current best practices on when to use class parameters, and when to explicitly look up values. The most relevant paragraph from that doc is this one:

Parameterized profiles are preferred over explicit Hiera lookups. Class parameters make lookups consistent and present them all in a standardized way. Users can quickly determine the data API of a class without having to read or understand its logic, and class parameters also expose data lookup information about a class that can be useful for potential integration with external systems. Explicit Hiera data lookups (via calls to the lookup() or hiera() functions) dilute these benefits.

tl;dr class parameters are usually the way to go.

edit flag offensive delete link more

Comments

Very through explanation! +1

DarylW gravatar imageDarylW ( 2018-03-23 08:55:28 -0500 )edit
0

answered 2018-03-21 12:23:13 -0500

andrew91 gravatar image

Thanks much! Looks like that answered my question perfectly plus some. I've went ahead and used the following code as recommended and everything is working now. I've also checked out the "data escalation path", which cleared a whole lot of things for me. Thanks again!

    class profiles::common::packages (
    $packages = lookup('packages::installed'),
) {
    package { $packages:
            ensure => installed,
              }
}
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2018-03-20 15:06:59 -0500

Seen: 44 times

Last updated: Mar 21