I have two classes in puppet and want to execute only one or the other.
Is this possible and if so how?
Thanks Guys
Puppet will only consider contents of classes that are included in your manifest.
class good_stuff {
...
}
class break_stuff {
...
}
include good_stuff
The above code will only apply resources from within the good_stuff class, not break_stuff.
Related
I have trouble formulating the following test with ArchUnit:
I want to ensure that all classes in a certain package only access classes outside of the application base package or within a certain sub package ("or" not "xor").
What I have got is:
#AnalyzeClasses(packages = "com.example")
public class ClassDependencies {
#ArchTest
static final ArchRule deps = classes.that()
.resideInAPackage("com.example.mymodule.some.package")
.should().onlyAccessClassesThat().resideOutsideOfPackage("com.example..")
.orShould().resideInAnyPackage("com.example.package1..", "com.example.package2..);
Problem is, that the or-condition should be within the onlyAccessClassesThat(). Above formulation fails if a class has both types of access, which I want to be valid.
How can I achieve what I want?
Thanks for any help on this...
You can specify provide the predicate as method argument and combine it with another predicate:
classes
.that().resideInAPackage("com.example.mymodule.some.package")
.should().onlyAccessClassesThat(
JavaClass.Predicates.resideOutsideOfPackage("com.example..")
.or(JavaClass.Predicates.resideInAnyPackage("com.example.package1..", "com.example.package2.."))
)
I'd like to use and configure the puppet-nginx module, although this is a general question about Puppet configuration.
Exec { path => [ "/bin/", "/sbin/" , "/usr/bin/", "/usr/sbin/" ] }
class nginx-setup {
class { 'nginx': }
}
include nginx-setup
Works great! Now, if I follow the docs for configuration I end up with something like this:
Exec { path => [ "/bin/", "/sbin/" , "/usr/bin/", "/usr/sbin/" ] }
class nginx-setup {
class { 'nginx': }
class { 'nginx::package':
package_source => 'nginx-mainline'
}
}
include nginx-setup
Error: Duplicate declaration: Class[Nginx::Package] is already declared
I tried include nginx instead of my first class declaration, but I think the module's init.pp is declaring the nginx::package class already and I still get duplicate declaration error. Even if that worked, what if I wanted to apply more configurations to another class within the nginx module? For example:
Exec { path => [ "/bin/", "/sbin/" , "/usr/bin/", "/usr/sbin/" ] }
class nginx-setup {
class { 'nginx': }
class { 'nginx::package':
package_source => 'nginx-mainline'
}
class { 'nginx::config':
nginx_error_log => 'syslog:server=localhost',
}
}
include nginx-setup
Many duplicate definitions!
So it feels like I should be passing everything required into my initial class declaration, but I can't seem to find the right way to do it. What is the best way to achieve this?
TL;DR
Consider using Hiera after all, for this module is tricky to use otherwise, due to some shortcomings in Puppet's handling of class parameters.
Long answer:
That's a loaded question, actually, even though it should not be. You correcly inferred the gist already. But let's take it step-by-step.
Module structure
It is now considered best practice (citation needed, although Ryan Coleman from Puppet Labs mentioned this in a recent presentation at FOSDEM) to expose all tunables of a module in its central class (here, class nginx).
This way, it is clear for the user that they need to look up the appropriate parameter for this one class, instead of going on a hunt for the appropriate class to tune.
The nginx module you picked seems to adopt this in large parts, but not consequently.
Hacks using defined()
As you have noticed, the module author added some shortcuts to allow you to declare your classes "safely" if you make sure the nginx::config class is encountered before the nginx class proper, lexically.
This is dangerous, because in a complex manifest, this might not be easy to assert.
include vs. class { }
Class parameters are problematic, because they lead to include being less safe than it used to be, because they don't mix well with class { 'name': ... } style declarations. The latter are always bad news because they have to be unique, as you are now experiencing.
It is best to stick to include as much as possible, which leads to the next issue.
Hiera
With parameterized classes, you really want to adopt Hiera as soon as possible. Defining class parameters as data is almost universally superior to doing it in the manifest. I understand the desire to stick to simple constructs first, but due to the issue described above, it can really make life harder on yourself.
It turns out it was module-specific. jfryman/puppet-nginx module classes are loaded automatically except for nginx::config (unless it isn't declared already) and most other classes inherit their settings from nginx::config. The correct solution for this module is;
class nginx-setup {
class { '::nginx::config':
http_access_log => 'syslog:server=localhost,tag=nginx,severity=info',
nginx_error_log => 'syslog:server=localhost,tag=nginx,severity=info',
}
class { '::nginx':
package_source => 'nginx-mainline',
}
}
include nginx-setup
jfryman/puppet-nginx is moving towards Hiera configurations and this might not work for long. I wanted a pure Puppet solution (to learn) before integrating Hiera but I wouldn't recommend it for everyone...
I am trying to create a "template" for all my servers. I have 2 configurations. An NTP client (which is taken care of in the baseclass class. I want to create an override specific for the NTP servers by declaring something specific in the node declaration. Something like "baseclass::ntp:restrict => true,". Or alternatively, how would I change one of the already declared variable from baseclass::ntp?
Does anyone have any ideas host to do this?
This is what I have so far:
templates.pp
class baseclass {
include defaultusers
include sudoers
include issue
class { ntp:
ensure => running,
servers => ['ntpserver1.host.com',
'ntpserver2.host.com',],
autoupdate => false,
}
}
nodes.pp
node default {
include baseclass
}
node "ntpserver1.host.com" inherits default {
<some code here to declare new variable in baseclass::ntp>
<some code here to change existing variable, such as "ensure">
}
You have run smack into the problem with parameterized classes: they don't support overrides. They should, but due to various problems with the order in which things are initialized in Puppet, you can't override parameters to classes. Once you set them, you're done. This is different from defines, where overriding parameters works as you expect. There's an open bug about this that a bunch of us have voted up and are watching, but there appears to be little progress.
Given that, my recommendation would be to recast your parameterized ntp class as a define instead, because a define will work exactly as you want. Change the class to something like:
define ntp($servers, $autoupdate = false, $ensure = 'running') {
# ... put code from class here ...
}
and then change baseclass to:
ntp { $fqdn:
servers => [ 'ntpserver1.host.com',
'ntpserver2.host.com',],
}
You will have to change the class structure to add a new class, since you can't inherit from a class in a node, so change your node to:
node "ntpserver1.host.com" inherits default {
include hosts::ntpserver1
}
or however you want to name your per-host configuration classes. Then, in that class, you can do exactly what you expect to be able to do:
class hosts::ntpserver1 inherits baseclass {
Ntp["$fqdn"] { ensure => 'stopped' }
}
I know this seems like a huge runaround, particularly if you're used to doing a bunch of stuff inside nodes (which don't participate in the class inheritance tree). But without being able to override parameters to classes, there doesn't seem to be a good alternative. (We manage 500+ nodes and about 100 completely separate service definitions, with hundreds of modules and a huge amount of variety between hosts, including per-host overrides, using this method and it works extremely well.)
TL,DR summary: You can't override class parameters. Once you've passed a parameter to a class in Puppet, you're done. You can override define parameters. Therefore, anything you want to override is better written as a define than a class. However, remember that override hierarchies means that you have to put the core of your node definition in a class, since only classes can inherit from and override another class. Therefore, if you use overrides heavily, get into the habit of having your node definitions be trivial (just including a class that does all the work) so that your classes can inherit from base classes and override the parameters to defines.
I accepted rra's answer, but I found a solution that worked for me a little better. It's a slight hack, I suppose:
template.pp
class baseclass ($ntprestrict = 'false') {
include defaultusers
include sudoers
include issue
class { ntp:
ensure => running,
servers => ['ntpserver1.host.com',
'ntpserver2.host.com',],
autoupdate => false,
restrict => $ntprestrict,
}
}
nodes.pp
node "ntpserver1.host.com" {
class { baseclass: ntprestrict => 'true' }
}
node "client.host.com" {
class { baseclass: ntprestrict => 'false' }
}
Can someone explain to me why would this work :
node 'puppetagent'{
$my_role="proxmoxnode"
include role_proxmoxnode
}
class role_proxmoxnode {
include sshdconf
}
And this won't :
node 'puppetagent'{
include role_proxmoxnode
}
class role_proxmoxnode {
$my_role="proxmoxnode"
include sshdconf
}
By "Work" I mean that the sshd_config.erb file set by sshdconf module will find the $my_role="proxmoxnode" as expected. By "won't work", I mean the template complaining with "Could not find value for 'my_role'"
I use puppet 3.0.
I followed the doc in http://projects.puppetlabs.com/projects/1/wiki/Infrastructure_Design_Guidelines about roles.
Thanks
In Puppet 3.0. unqualified variables are looked up in 4 places:
Local scope
Inherited from a base class
Node-level
Top scope
Local scope, by the way, would apply to variables defined in the class, not in classes which simply include it.
So, in your first example, we go looking:
Is it local? No.
Is it in a base class? No.
Is it in the node? yes. We stop.
In the second example...
Is it local? No.
Is it in a base class? No.
Is it in the node? No.
Is it in top scope? No. Fail.
Clear?
I want to pass node specific information to a class, which then could evaluate it for specific purposes. Actually this question consists of three parts.
Say, I have the following node:
node 'devbox' {
$serverType = 'something'
include someClass
someOtherClass { 'someOtherClass':
par1 => 'value',
}
targetClass { 'nodeInformationShouldGoHere': }
}
Inside targetClass, I want to evaluate if serverType, someClass or someOtherClass is set (e.g. with if-else). My questions now are:
Is setting and passing the variable suitable in puppet for this?
or should I use tags (as the classes are automatically tagged for this node)?
Are their further approaches and what are limitations to above ones (e.g. do they work for resource types?)?
You can absolutely use puppet this way. Read over the documentation for Parameterized Classes and see if that meets your needs.