20

I'm writing some puppet modules and have a package defined in two modules hence get the following error:

err: Could not retrieve catalog from remote server: Error 400 on SERVER: Duplicate definition: Package[gnome-session-fallback] is already defined in file /etc/puppet/modules/vnc4server/manifests/init.pp at line 3; cannot redefine at /etc/puppet/modules/vino/manifests/init.pp:7 on node l

Hence want to ensure that the package has not already been defined but the following does not work:

if ! defined ('gnome-session-fallback') {
    package { 'gnome-session-fallback':
        ensure => installed,
    }
}

Can anyone suggest how to fix this, and on the broader scale, what is the "proper" approach to avoiding clashes such as this in modules?

5
  • Please post exactly how this does not work. Do you get an error message, or it just simplz does not do what it is supposed to? Also please include which version of Puppet you are using! Commented Mar 7, 2013 at 8:35
  • Error message posted on the second line above - I am testing if its already defined in another module and the test does not seem to detect this and hence attempts to redefine it and the agent run fails (see err). Version 2.7.11 Commented Mar 7, 2013 at 8:44
  • Maybe I'm a bit dull today: so you get the error with the if ! defined... script, right? Commented Mar 7, 2013 at 8:47
  • The error is as posted in the original post "Error 400 on SERVER: Duplicate definition: Package" etc because the if ! defined test is not working. Commented Mar 7, 2013 at 11:05
  • See my comment below, @MrMorphe. Commented Apr 13, 2016 at 19:10

4 Answers 4

46

You are missing Package[] inside defined(). The correct way to do it:

if ! defined(Package['gnome-session-fallback']) {
    package { 'gnome-session-fallback':
        ensure => installed,
    }
}
Sign up to request clarification or add additional context in comments.

Note that it doesn't work in all cases because defined() is dependent on parse order and there's a bug for it opened for a long time.
14

The cleanest way to do this is to use the ensure_resource function from puppetlabs-stdlib:

ensure_resource('package', 'gnome-session-fallback', {'ensure' => 'present'})

an even cleaner function to do this from said library is ensure_packages(['pkg1', 'pkg2'])
5

To answer my own question about what the "proper" approach is : This issue is discussed at https://groups.google.com/forum/?fromgroups=#!topic/puppet-users/julAujaVsVk and jcbollenger offers what looks like a "best-practice" solution - resources which are defined multiple times should be moved into their own module and included into the classes on which they depend. I applied this and solved my problem.

This doesn't actually answer why "if !defined" fails however...

Comments

1

One cleaner way (among multiple ways) is to create a virtual package resource and then realize it. You can realize the same virtual package multiple times without error.

@package { 'gnome-session-fallback':
    ensure => installed,
}

And then where you need it:

realize( Package[ 'gnome-session-fallback' ] )

Comments

Your Answer

Draft saved
Draft discarded

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.