Puppet run ordering for optional classes

dependencies, puppet

Solution

If Class[mysql] is optional, then you can try checking if it exists with the defined() function:

 if defined(Class['mysq'l]) {
   Class['mysql'] -> Class['webserver']
 }

Here's some sample code I used to test this out:

class optional {
    notify{'Applied optional':}
}

class afterwards {
    notify{'Applied afterwards':}
}

class another_optional {
    notify{'Applied test2':}
}

class testbed {

    if defined(Class['optional']) {
            notify{'You should see both notifications':}
            Class['optional'] -> Class['afterwards']
    }


    if defined(Class['another_optional']) {
            notify{'You should not see this':}
            Class['another_optional'] -> Class['afterwards']
    }
}

node default {
     include optional
     include afterwards
     include testbed
}

After executing with a 'puppet apply test.pp', it generates this output:

notice: You should see both notifications
notice: /Stage[main]/Testbed/Notify[You should see both notifications]/message: defined 'message' as 'You should see both notifications'
notice: Applied optional
notice: /Stage[main]/Optional/Notify[Applied optional]/message: defined 'message' as 'Applied optional'
notice: Applied afterwards
notice: /Stage[main]/Afterwards/Notify[Applied afterwards]/message: defined 'message' as 'Applied afterwards'
notice: Finished catalog run in 0.06 seconds

I tested with puppet 2.7.1 on Ubuntu 11.10

Problem

I am trying to solve the following problem with Puppet: I have multiple nodes. Each node includes a collection of classes. For instance, there is a `mysql` class and `webserver` class. node1 is a webserver only, node2 is webserver + mysql. I want to specify that IF a node has both webserver and mysql, the mysql install will happen before webserver. I cannot have `Class[mysql] -> Class[webserver]` dependency, because the MySQL support is optional. I tried to use stages, but they seem to introduce dependencies between my classes, so if I have e.g. this: ``` Stage[db] -> Stage[web] class { 'webserver': stage => web ; 'mysql': stage => db ; } ``` and I include the webserver class in my node ``` node node1 { include webserver } ``` .. the mysql class gets included as well! That is not what I want. How can I define order on optional classes? Edit: here is the solution: ``` class one { notify{'one':} } class two { notify{'two':} } stage { 'pre': } Stage['pre'] -> Stage['main'] class { one: stage=>pre; # two: stage=>main; #### BROKEN - will introduce dependency even if two is not included! } # Solution - put the class in the stage only if it is defined if defined(Class['two']) { class { two: stage=>main; } } node default { include one } ``` Result: ``` notice: one notice: /Stage[pre]/One/Notify[one]/message: defined 'message' as 'one' notice: Finished catalog run in 0.04 seconds ``` ~

Original source