On Thursday, January 2, 2014 8:28:33 AM UTC-6, Jelle B. wrote:
>
> Hi all,
>
> I have been kinda stuck with the following few issues (all related to one
> and other)
>
> What I want ot ddo is define a couple of standard actions in puppet that I
> can use across all my classes.
> So for example I define a exec for apt-get update , or a reload. When
> built in to a class it works fine I would just have to redeclare it with an
> other name in the next class and I want to get away from it.
>
>
Part of your problem may be that you have a wrong conception of Puppet
DSL. The DSL is not a scripting language; in fact, it is not an imperative
language at all. There are no "actions" in it. You need to discard the
mindset that you are telling Puppet what to do. Instead, embrace the
concept that you are describing to Puppet what state it needs to achieve.
> Now I have started working on importing it via my site.pp but I can not
> define say the exec for "service $service_name reload", it will generate an
> error when I include it : Must pass service_name to Class[Defaults] (class
> defaults being the collective class I brought all these snippets together)
>
>
With respect to services in particular, you are likely to be better off
relying on the Service resource than to roll your own service management
via Exec resources.
> So question one am I on the right path in creating this , using the top
> scope prinocipal in my design for this.
>
>
I think not, but it's hard to tell because I don't know what you mean by
"using the top-scope principal". On the other hand, you are right to be
trying to consolidate redundant declarations and to avoid repeating
yourself.
> Second question how do I pass a variable in this setup , as I can not
> include the class in site.pp as it will generate the "must pass error" but
> just doing an import in my site.pp and then an include in my module init.pp
> does not actually work either but then silentlly.
>
>
The "import" function and the "include" function do very different things.
You use "import" to persuade Puppet to parse a *manifest file* that it
otherwise would not parse (because it's in the wrong place for the
autoloader to find it or because there is nothing to trigger the autoloader
to load it in the first place). That has little to do with declaring
classes on the target node, and there are very few good use cases for it in
modern Puppet. Instead, put your classes and defined types in modules,
laid out appropriately for autoloading.
The "include" function, on the other hand, instructs Puppet that the named
*class* must be included in the target node's catalog. That is sometimes
referred to as "declaring" the class. This form of class declaration does
not explicitly specify any class parameters, which can be useful.
In your case, however, it appears that your class has a defined parameter
with no default value. If you must use class parameters -- a discussion
that I will omit for now -- then you must ensure that each parameter of
each declared class is assigned a value exactly once. Parameter values can
come from these places (from highest precedence to lowest):
- from a parameterized-style class declaration or ENC-based class
declaration
- from hiera via automated data binding (Puppet 3+ only)
- from a default value specified in the class itself
I predict that you will be inclined to use parameterized-style class
declarations, but I urge you to avoid them. They will cause you grief.
Instead, avoid parameterization where it is unneeded, define sensible
default parameter values, and use Hiera to provide parameter overrides
where necessary.
> I am missing somethign I think just not sure what and where .
>
>
You are missing several things, I suspect. Among them may be that
- classes are idempotent -- declaring the same class more than once has
no different meaning than declaring it exactly once
- defined types and custom functions are therefore better vehicles for
parameterized declarations that you want to reuse within the scope of the
same node's catalog
- Puppet terminology incorporates some words from the object-oriented
programming world that may mislead people with OO programming background.
In particular,
- a Puppet "class" is not a model or type for objects, rather it
represents a classification of the target node. There are no class
instances, or if that's too alien for you then you can consider all
Puppet
classes to be Singletons.
- Puppet class and node inheritance does not work the way OO
programmers tend to expect.
- A few other Puppet keywords and terminology sometimes trip up people
coming from a programming background, not necessarily OO:
- Defined types, created via the "define" keyword, are not analogous
to C preprocessor macros. They are more like OO classes (a lot more so
than Puppet classes are, in fact), such that we sometimes talk about
"defined type instances" or similar.
- Unlike the C preprocessor macro and similar statements in several
other programming languages, Puppet's "include" statement does not
perform
textual interpolation. I already covered what it actually does do.
- The "import" statement does not perform textual interpolation
either, though what it actually does do is fairly similar to what
Python's
"import" does.
> Here below the code snippets of what I am doing.
>
> site.pp in /etc/puppet/environments/dev/manifests/
> Exec { path => [ "/bin/", "/sbin/" , "/usr/bin/", "/usr/sbin/" ] }
>
>
Ok. A default path for all Execs is a reasonably sensible thing. If you
are using third-party modules, however, then I would be very cautious about
setting global defaults. Even something as innocuous as that could
conceivably cause trouble for a module that did not expect it.
> import 'classes/*.pp'
>
>
No. Do not use 'import' to load class definitions. Instead, put your
classes into one or more modules, and lay them out where the autoloader
will find them.
> the defaults.pp with the class from
> /etc/puppet/environments/dev/manifests/classes/ :
> class defaults ( $service_name ){
>
>
To put this properly in a module named "site", change the class name to
"site::defaults"
class site::defaults ($service_name) {
and move the file to
/etc/puppet/environments/dev/modules/site/manifests/default.pp. In your
puppet.conf, make sure the master's configuration for the "dev" environment
has "/etc/puppet/environments/dev/modules" as or in its module path.
(Though in truth, I would leave environments for later if I were you.)
> case $::operatingsystem {
> debian, ubuntu: {
> exec { "apt update":
> command => "/usr/bin/apt-get update",
> # onlyif => < snipped >
> }
> }
> }
>
> exec { "reload":
> command => "/usr/sbin/service $service_name reload",
> refreshonly => true,
> require => Service[[$service_name]],
> }
>
> exec { "restart":
> command => "/usr/sbin/service $service_name restart",
> refreshonly => true,
> require => Service[[$service_name]],
> }
>
>
Those particular Execs pretty much duplicate functionality that the Service
resource provides already. If you trigger a refresh on a running Service
resource then the service will be restarted.
>
> }
>
>
Overall, however, the class doesn't make sense. More specifically, it
doesn't make sense to parameterize the class with a service name, because
classes are idempotent. You would only be able to use it once, anyway.
You might, however, be able to make use of something like this as a defined
type.
> And the class calling it from
> /etc/puppet/environments/dev/modules/pdns/init.pp
>
> include defaults
>
>
See above: include does not perform textual interpolation. (Also, classes
are not analogous to macros.)
> class pdns_33 ( $mysql_password, $srv_type, $web_password ) {
> <-- snipped -->
> file { "/etc/powerdns/pdns.conf":
> ensure => present,
> owner => root,
> group => root,
> mode => 644,
> content => template("pdns_33/pdns.conf.erb"),
> notify => Exec[[reload]],
> }
> <-- snipped -->
>
>
What you are trying to do will not work. Puppet DSL does not have macros.
If your intended uses are similar enough to each other, then you might be
able to achieve at least some of what you're after via a defined type, but
in general, you're approaching the whole thing in a very non-idiomatic way.
Successful and effective Puppet manifest design is an exercise in *modeling*,
not programming. Your objective is to model the target configuration of
your nodes. It follows that when writing manifests you should be thinking
primarily in terms of describing the configuration artifacts you want
Puppet to manage, rather than in terms of specifying actions for Puppet to
perform.
Recommended reading:
- http://docs.puppetlabs.com/puppet/3/reference/lang_summary.html
- http://docs.puppetlabs.com/puppet/3/reference/modules_fundamentals.html
-
http://www.devco.net/archives/2012/12/13/simple-puppet-module-structure-redux.php
Additionally, you should at least skim these:
- http://docs.puppetlabs.com/references/3.stable/type.html
- http://docs.puppetlabs.com/references/3.stable/function.html
John
--
You received this message because you are subscribed to the Google Groups
"Puppet Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/puppet-users/ddad9657-6496-41f7-bf0f-e8fee43df7fe%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.