The use case i try to illustrate is when to declare some item (eq mysqld service) with a default configuration that could be included on every node (class stripdown in the example, for basenode), and still be able to override this same item in some specific class (eg mysql::server), to be included by specific nodes (eg myserver.local)

I illustrated this use case with the example below, where i want to disable mysql service on all nodes, but activate it on a specific node. But of course, Puppet parsing fails because the Service[mysql] is included twice. And of course, class mysql::server bears no relation to be a child of class stripdown

Is there a way to override the Service["mysql"], or mark it as the main one, or whatever ? I was thinking about the virtual items and the realize function, but it only permits apply an item multiple times, not to redefine or override.

# In stripdown.pp :
class stripdown {
    service {"mysql": enable => "false", ensure => "stopped" }
}

# In mysql.pp :
class mysql::server {  
    service { mysqld:  
        enable      => true,  
        ensure      => running,  
        hasrestart  => true,  
        hasstatus   => true,  
        path        => "/etc/init.d/mysql",  
        require     => Package["mysql-server"],  
    }
}

# Then nodes in nodes.pp :
node basenode {
    include stripdown
}

node myserver.local inherits basenode {  
    include mysql::server`         # BOOM, fails here because of Service["mysql"] redefinition             
}
link|improve this question
feedback

4 Answers

Have a go with this:

# In stripdown.pp : 
class stripdown {
    service { "mysql": 
         enable => "false", 
         ensure => "stopped" 
    }
}

# In mysql.pp : 
class mysql::server {  

    if defined(Service["mysql"]) {
        Service["mysql"] {  
            enable     => true,  
            ensure     => running,  
            hasrestart => true,  
            hasstatus  => true,  
            path       => "/etc/init.d/mysql",  
            require    => Package["mysql-server"],  
        }
    } else {
        service { "mysql":  
            enable     => true,  
            ensure     => running,  
            hasrestart => true,  
            hasstatus  => true,  
            path       => "/etc/init.d/mysql",  
            require    => Package["mysql-server"],  
        }
    }
}

# Then nodes in nodes.pp : 
node basenode {
    include stripdown 
}

node myserver.local inherits basenode {  
    include mysql::server
}

This of course comes with the caveat that you already have Package["mysql-server"] defined elsewhere was it will fail as written without it due to your require statements.

The other error I found was that you had too many spaces after the options. There options in the stanza must be aligned no more than 1 space greater than the longest option name.

link|improve this answer
feedback

Whenever you find yourself saying "I want this component to behave one way in one node, but a different way in another node", you probably need to be looking at a definition driven by variables, either via case statements in the class definition, or substitutions in a template.

Unfortunately, your example shows you attempting to use inheritance, which is pretty badly broken in puppet and will cause you a lot of grief here because one of the things that it breaks is variable redefinition in nodes.

The way that I generally handle something like this is to create a 'default_parameters.pp' file that has nothing in it but default assignments for a long list of variables, so in this case, it would contain a line something like $mysql_enabled = false. This file is then included by the module's init.pp file. Then, the node definitions file would look something like:

import "mymodule"

node myserver.local {   # NOTE: no inheritance!
  $mysql_enabled = true
  include mysql::server
}

node otherserver.local {
  include mysql::server
}

Then in the class definition for mysql::server you check if $mysql_enabled is true, and if so, use a selector on enable and ensure.

This breaks instantly if node myserver.local inherits anything, because that will lock the value of the variables at inherit time, and further changes inside the node definition will have no effect, but otherwise I use this technique all over the place to have individual components behave differently without generating multiple classes.

If you absolutely have to have inheritance, but the list of machines with mysql enabled is small, you can take an alternate route: instead of setting a variable in the node definition, build your selector off of $fqdn, with the default to disable, and selected fqdns enabled.

link|improve this answer
interesting, i have to try this. Currently, i have a whole scheme with variables and an exec in a define (this works), which i partially described on the puppet mailing list. This was a long discussion, but in the end, no one could find a way to do it – user28679 Mar 3 '10 at 16:13
feedback

Give this a go

# In stripdown.pp : 
class stripdown {
    service { "mysql": 
         enable => "false", 
         ensure => "stopped" 
    }
}

# In mysql.pp : 
class mysql::server inherits stripdown {  
    Service["mysqld"] {  
        enable      => true,  
        ensure      => running,  
        hasrestart  => true,  
        hasstatus   => true,  
        path        => "/etc/init.d/mysql",  
        require     => Package["mysql-server"],  
    } 
}

# Then nodes in nodes.pp : 
node basenode {
    include stripdown 
}

node myserver.local inherits basenode {  
    include mysql::server
}
link|improve this answer
Yes, i know about inheritance, but i do not want it in this case because the class mysql::server does not have relationship with the stripdown class. And moreover the mysql::server already inherits the class mysql I did find a way by using variables and execs, but it seems i run into strange puppet behavior, as it seems global variables of a class are set even if the class is not included by the node – user28679 Dec 11 '09 at 14:09
feedback

One thing you may want to look at is Virtual Ressources to get around the multiple definition of ressources. Documentation on that topic can be found : http://reductivelabs.com/trac/puppet/wiki/VirtualResources

Of course, the other way would be to simple create node objects for each host that does not run mysql and then load the stripped class there.

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.