I get a "duplicate definition problem" with Puppet 0.24.8 when using
virtual ressource in a define:
Here is a sample :
define mydefine1 {
@package { postfix: }
}
define mydefine2 {
mydefine1 { $name: }
realize Package[postfix]
}
mydefine2 { test1: }
mydefine2 { test2: }
Here is the problem:
Puppet::Parser::AST::Resource failed with error ArgumentError:
Duplicate definition: Package[postfix] is already defined in file
test.pp at line 2
If i move the virtual resource in a class all is working fine. For instance:
class common {
@package { postfix: }
}
define mydefine1 {
include common
}
define mydefine2 {
mydefine1 { $name: }
realize Package[postfix]
}
mydefine2 { test1: }
mydefine2 { test2: }
Does someone know if it's a bug or if i'm doing things the wrong way?
Thanks!
Ex:
class clspackage
{
@package { postfix: }
}
define mydefine1 {
include clspackage
}
define mydefine2 {
mydefine1 { $name: }
realize Package[postfix]
}
Silviu
As Sliviu explained, you're doing things the wrong way. What he gave
you resolve your errors, but it is focused on how to get the virtual
package declaration to work. Depending on what you're trying to
accomplish, however, a virtual declaration may be a sub-optimal
approach to begin with.
I'm inferring that you want a define that may be called multiple
times, with every invocation needing to declare the same one resource
(among other things). In Puppet, you can achieve this directly with
classes -- involving virtual resources only complicates matters.
Thus, within the limited scope of the example, this solution will
achieve exactly the same result (effect of mydefine2) as Sliviu's
example:
class clspackage {
package { postfix: }
}
define mydefine1 {
include clspackage
}
define mydefine2 {
mydefine1 { $name: }
}
In general, although virtual resources seem cool, they don't do as
much as Puppet newcomers seem to think they do. I'm unaware of any
problem whose solution *requires* their use, and people seem inclined
to apply them to situations where they aren't helpful. YMMV.
John
Here is the same problem by another Puppet user:
http://www.mail-archive.com/puppet...@googlegroups.com/msg06262.html
2010/1/11 jcbollinger <John.Bo...@stjude.org>:
> --
> You received this message because you are subscribed to the Google Groups "Puppet Users" group.
> To post to this group, send email to puppet...@googlegroups.com.
> To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
>
>
>
>
On Jan 11, 3:41 pm, Sébastien Prud'homme
<sebastien.prudho...@gmail.com> wrote:
> Thanks for the responses. My example is just an example. My real
> "define" has some parameters so it's not possible to use a class.
Whether 'mydefine1' has parameters is irrelevant to whether you can
achieve your configuration goal by putting the package declaration
into a class.
Are you trying to say that the parameters to 'mydefine1' are used to
set properties of the Package resource? That cannot work if
'mydefine1' is called more than once with different parameters.
Resources describe the desired state of the system, so it doesn't even
make sense to declare the same resource differently in different parts
of the same catalog. It is impossible to accommodate multiple
different specifications, because a resource can have only one state
at a time.
On the other hand, if the parameters for the package will be the same
every time 'mydefine1' is called within each given node's catalog,
then you definitely can put the package declaration (virtual or not)
into a class. You don't have to convert 'mydefine1' into a class, as
our examples show: you can put the package into an existing class if
there's a suitable one, or you can create a new class for it, as in
the example. It is still quite possible to customize the package's
parameters for each node.
You may need to rearrange your manifests more than you hoped before
they work, but there is no avoiding the prohibition against multiple
declarations of the same resource. We may be able to provide better
help if you are more specific about what you're trying to do.
The example is just there to show the duplicate problem that i don't
understand as i use a virtual ressource.
Here is another one:
define mydefine1 {
@file{ "/$name": ensure => directory }
}
define mydefine2($dir) {
mydefine1 { $dir: }
realize File["/$dir"]
file{ "/$dir/$name": ensure => directory }
}
mydefine2 { test1: dir => test}
mydefine2 { test2: dir => test}
I've got a lot of mydefine2 to declare. Sure a workaround would be to
add all the mydefine1 declarations in one single class and remove it
from mydefine2 but i find it's not an elegant solution.
2010/1/12 jcbollinger <John.Bo...@stjude.org>:
On Jan 12, 4:19 pm, Sébastien Prud'homme
<sebastien.prudho...@gmail.com> wrote:
> The example is just there to show the duplicate problem that i don't
> understand as i use a virtual ressource.
Each resource can be *declared* only once within any node's catalog,
no matter whether that declaration is concrete or virtual (or
exported). Virtual resources may be *realized* any number of times.
In your examples, multiple invocations of your "mydefine1" are
declaring the *same* (virtual) resource, hence Puppet complains.
A common usage model for virtual resources is to create a class
declaring all the virtual resources of a certain type that any of your
nodes might want, and then have different nodes realize the ones they
need. The canonical example seems to be system users; I believe the
best practices document describes that.
> define mydefine1 {
> @file{ "/$name": ensure => directory }
> }
[...]
> mydefine1 { $dir: }
> realize File["/$dir"]
I see that pattern sometimes, and it is NEVER useful. Specifically,
it is not useful to declare a virtual resource and then immediately
realize it, for that is only a more complicated way of declaring a
concrete resource. Again, resource declarations may not be
duplicated, virtual or not. Only *realizations* may be duplicated.
> I've got a lot of mydefine2 to declare. Sure a workaround would be to
> add all the mydefine1 declarations in one single class and remove it
> from mydefine2 but i find it's not an elegant solution.
Sorry, no help for that. Personally, I would find it inelegant to
declare the same resource multiple times (even if the code were not
duplicated), so I'm not bothered in the slightest that Puppet
disallows it.
Suppose you moved the mydefine1 calls out of mydefine2 into whatever
class contains all the mydefine2 calls? That still keeps it nicely
packaged together:
class somefiles {
define mydefine1 {
...
}
define mydefine2($dir) {
...
}
mydefine1 {"dir1": }
mydefine2 { "test1": dir => "dir1" }
mydefine2 { "test2": dir => "dir1" }
mydefine1 {"dir2": }
mydefine2 { "test3": dir => "dir2" }
mydefine2 { "test4": dir => "dir2" }
}
YMMV, but I don't see anything inelegant about that.
John
On Jan 13, 8:47 am, jcbollinger <John.Bollin...@stJude.org> wrote:
> YMMV, but I don't see anything inelegant about that.
Note also that you can then simplify your definitions by making the
virtual file declaration concrete and removing the realize() call.
You might even be able to remove the "dir" parameter to mydefine2.
Surely simpler code contributes to elegance.
John
Thanks a lot again.
2010/1/13 jcbollinger <John.Bo...@stjude.org>: