Re: [Puppet Users] How to only apply my manifests to certain classes?

156 views
Skip to first unread message

Matthew Burgess

unread,
Dec 20, 2012, 11:51:40 AM12/20/12
to puppet...@googlegroups.com
On Thu, Dec 20, 2012 at 4:11 PM, Steve Button <steve....@gmail.com> wrote:
> Hi,
>
> I've written a new resolv class, but I only want it to get pushed out (for
> instance) UAT servers for now. Or perhaps just servers which have apache
> installed, or just the ones which are part of project xyz.

Depending on the size and complexity of your environment, there's
several ways of achieving those goals.

> I've been searching through the docs, but I think I'm looking in the wrong
> place. Also, I get the feeling that there's several ways to achieve this and
> some of the docs refer to the older ways.

Yes, there are several ways, and I think the docs cover all of them,
at least to a certain degree.

> What's the current method of limiting certain manifests to certain classes
> of machines? (have I got my terminology wrong here?)

Using the word 'classes', whilst not incorrect, may cause confusion,
as a class is something special in puppet terminology.

> Perhaps someone could put a link in to the best place in the docs that
> explains this to me? I'm sure I've read about this in the past, but I can't
> seem to find it again.

OK. If you're trying to apply your resolv class based on the fact
that Apache is installed, I'd recommend resource dependencies (docs at
http://docs.puppetlabs.com/learning/ordering.html):

apache { 'vhost-title':
parameter => value,
param2 => value,
before => resolv['resolv.conf']
}

I personally don't like having dependencies ordered that way (I prefer
'require'), but given your use case of 'I know which servers I want
Apache on, and resolv needs to be put on those same servers' this
seems to be the more natural way of writing your manifest.

The most flexible way of assigning classes to nodes is via an External
Node Classifier, or ENC. Documentation at
http://docs.puppetlabs.com/guides/external_nodes.html. I think this
is generally considered the 'correct' method, given that manually
updating site.pp is just unworkable in any large(ish) setup.

For your 'I want to assign the class to all servers in XYZ project',
the first question you have to answer is 'how do you define which
servers are in project 'xyz'. If it's hostname based, your ENC has
direct access to that (the ENC script is called with the hostname as a
parameter). If it's some other property of the server, it may already
be available as a facter variable, which are easily obtainable via
calling out to the 'facter' binary in your script. If it's some other
property, you'll have to somehow make that available to your ENC
script. That could be done via a custom fact, which is documented at
http://docs.puppetlabs.com/guides/custom_facts.html.

Regards,

Matt.

Roman Shaposhnik

unread,
Dec 20, 2012, 11:51:59 AM12/20/12
to puppet...@googlegroups.com
On Thu, Dec 20, 2012 at 8:11 AM, Steve Button <steve....@gmail.com> wrote:
> Hi,
>
> I've written a new resolv class, but I only want it to get pushed out (for
> instance) UAT servers for now. Or perhaps just servers which have apache
> installed, or just the ones which are part of project xyz.

There are a couple of ways how you can achieve that depending
on your existing setup of Puppet:
* via ENC (external node classifier)
http://docs.puppetlabs.com/guides/external_nodes.html
* node definition
http://docs.puppetlabs.com/puppet/2.7/reference/lang_node_definitions.html
* good ol' case statements in your site.pp
case $::fqdn {
....
}
* manual execution of puppet apply with that single class given to it
echo 'your_class' | puppet apply

Please let us know a bit more about your setup.

Thanks,
Roman.

Ellison Marks

unread,
Dec 20, 2012, 2:47:16 PM12/20/12
to puppet...@googlegroups.com
An option that hasn't been mentioned yet is hiera. It's great to use for data, but you can also use it to say what classes get applied to what nodes. You define some variable in your hierarchy, say 'classes', which is an array of class names to be included, and then in your default node definition, you use hiera_include('classes'), which will get the names from all 'classes' variable in the hierarchy that matches the node checking in and include them.


On Thursday, December 20, 2012 8:11:42 AM UTC-8, Steve Button wrote:
Hi,

I've written a new resolv class, but I only want it to get pushed out (for instance) UAT servers for now. Or perhaps just servers which have apache installed, or just the ones which are part of project xyz.

I've been searching through the docs, but I think I'm looking in the wrong place. Also, I get the feeling that there's several ways to achieve this and some of the docs refer to the older ways.

What's the current method of limiting certain manifests to certain classes of machines? (have I got my terminology wrong here?) 

Perhaps someone could put a link in to the best place in the docs that explains this to me? I'm sure I've read about this in the past, but I can't seem to find it again.

Thanks in advance! 

jcbollinger

unread,
Dec 20, 2012, 5:51:37 PM12/20/12
to puppet...@googlegroups.com


On Thursday, December 20, 2012 10:51:40 AM UTC-6, Matthew Burgess wrote:
On Thu, Dec 20, 2012 at 4:11 PM, Steve Button <steve....@gmail.com> wrote:

OK.  If you're trying to apply your resolv class based on the fact
that Apache is installed, I'd recommend resource dependencies (docs at
http://docs.puppetlabs.com/learning/ordering.html):

apache { 'vhost-title':
  parameter => value,
  param2 => value,
  before => resolv['resolv.conf']
}



Unfortunately, that doesn't address the question.  The 'before' and 'require' metaparameters direct the ordering of resources that have been declared, but they do not themselves declare resources.  The resources they reference must be declared separately (and those declarations must have already been parsed).

This answer does lead toward a general Puppet truth however: it is preferable to tell Puppet how things should be instead of asking it to adapt to how things are.  Thus, if Apache servers should all have your 'resolv' class then your manifests should ensure that nodes you are configuring with Apache also get resolv.

 
I personally don't like having dependencies ordered that way (I prefer
'require'), but given your use case of 'I know which servers I want
Apache on, and resolv needs to be put on those same servers' this
seems to be the more natural way of writing your manifest.


Except that the declaration doesn't say that.  In fact, a relationship is probably not warranted here at all, because it doesn't matter (probably) in which order the resources are applied to target nodes -- it only matters that nodes that get Apache also get resolv.

 

The most flexible way of assigning classes to nodes is via an External
Node Classifier, or ENC.  Documentation at
http://docs.puppetlabs.com/guides/external_nodes.html.  I think this
is generally considered the 'correct' method, given that manually
updating site.pp is just unworkable in any large(ish) setup.


I think that's overstating it a bit.  An ENC is certainly a viable solution, and a lot of people use them, but in some ways they can be a lot more tedious and error prone than well-written manifests.  Even if your site uses an ENC, when you have firm configuration rules that can be expressed in Puppet DSL then it is better to express them that way.

For example, supposing that class 'resolv' is not parametrized or does not need to be declared with custom parameters (one of which should be your goal), and supposing that you have a class 'apache' with which you configure your apache nodes, all you need to do to ensure that all apache servers have class 'resolv' is put

    include 'resolv'

at the top of class apache's body.  Done.
 

For your 'I want to assign the class to all servers in XYZ project',
the first question you have to answer is 'how do you define which
servers are in project 'xyz'.  If it's hostname based, your ENC has
direct access to that (the ENC script is called with the hostname as a
parameter).  If it's some other property of the server, it may already
be available as a facter variable, which are easily obtainable via
calling out to the 'facter' binary in your script.  If it's some other
property, you'll have to somehow make that available to your ENC
script.  That could be done via a custom fact, which is documented at
http://docs.puppetlabs.com/guides/custom_facts.html.



All true, but none of it elects an ENC as the best consumer of the data.  I'd rate hiera as a particularly good approach for a case such as this one.


John

Steve Button

unread,
Dec 21, 2012, 6:10:45 AM12/21/12
to puppet...@googlegroups.com
On Thursday, 20 December 2012 16:51:59 UTC, rvs wrote:
On Thu, Dec 20, 2012 at 8:11 AM, Steve Button <steve....@gmail.com> wrote:
> Hi,
>
> I've written a new resolv class, but I only want it to get pushed out (for


Please let us know a bit more about your setup.

Thanks,
Roman.

I've used puppet before at several companies, but it's always been already set up before I arrived and I've only modified the existing manifests. 

Currently I'm at a new site and we're not using Puppet at all, just at the proof of concept stage. 

I'm aware Puppet is very powerful, which also means it could be very dangerous. I'd like to avoid bringing down the whole IT infrastructure (of course) by rolling out a change to resolv.conf, for example, which could potentially cripple a node. When I make a change I'd like to first test it on one single node, then perhaps 10 in Dev, then after a day or so the rest of Dev. Likewise for UAT and Prod environments. So, that's one requirement... to be able to roll things out gradually to give it time to spot mistakes in the code. 

I guess the apache / resolv example is a little contrived, and doesn't represent a real use case. More likely we might want certain packages / kernel setting on our Oracle servers, but different ones on our SAP servers. Looking at the example pointed to...

node 'www1.example.com', 'www2.example.com', 'www3.example.com' { include common include apache, squid }

I guess I could add "include uat" and then put things that are specific to UAT servers only in there.

Thanks for all the pointers, I think I've got a lot of reading to do and feeling a little overwhelmed!

joe

unread,
Dec 22, 2012, 11:27:54 PM12/22/12
to puppet...@googlegroups.com
This is an excellent post on how to organize those types of dependencies.

http://www.craigdunn.org/2012/05/239/
Reply all
Reply to author
Forward
0 new messages