是的,这很正常。Puppet 只允许资源声明一次。一般来说,如果你有这样的代码:
class aaa {
notify { 'xxx': message => 'yyy' }
}
class bbb {
notify { 'xxx': message => 'yyy' }
}
include aaa
include bbb
Puppet 应用它,您将看到如下错误:
Error: Evaluation Error: Error while evaluating a Resource Statement,
Duplicate declaration: Notify[xxx] is already declared at (file: ...test.pp,
line: 2); cannot redeclare (file: ...test.pp, line: 6) (file: ...test.pp, line: 6,
column: 3) on node ...
解决方法
解决方案 1 重构,使两个类都继承第三个类
通常,解决此问题的最佳方法是重构您的代码,以便有一个包含重复资源的第三个类,而其他类包括使用该include
函数的类,如下所示:
class ccc {
notify { 'xxx': message => 'yyy' }
}
class aaa {
include ccc
}
class bbb {
include ccc
}
include aaa
include bbb
这很好用。
请注意,这仅有效,因为该include
函数可以被多次调用,这与资源声明不同 - 也与类似资源的类声明不同。
你可以在这里阅读更多关于“include-like v resource-like class declarations”的信息。
解决方案 2 使用虚拟资源
您还可以使用虚拟资源。像这样重构:
class ccc {
@notify { 'xxx': message => 'yyy' }
}
class aaa {
include ccc
realize Notify['xxx']
}
class bbb {
include ccc
realize Notify['xxx']
}
include aaa
include bbb
另一个优点是您可以使用资源收集器并从一组虚拟资源中仅选择特定资源,如下所示:
class ccc {
@notify { 'ppp': message => 'xxx' }
@notify { 'qqq': message => 'yyy' }
@notify { 'rrr': message => 'zzz' }
}
class aaa {
include ccc
Notify <| message == 'xxx' |>
}
class bbb {
include ccc
Notify <| message == 'xxx' or message == 'yyy' |>
}
include aaa
include bbb
如果您在这里不需要此功能,就像出现的情况一样,您可能应该使用第一个建议。
解决方案 3 使用确保资源
另一个选项是ensure_resources
stdlib 中的函数:
class aaa {
ensure_resources('notify', {'xxx' => {'message' => 'yyy'}})
}
class bbb {
ensure_resources('notify', {'xxx' => {'message' => 'yyy'}})
}
include aaa
include bbb
解决方案 4 使用定义
从历史上看,这是强烈建议不要使用的,尽管文档没有提到任何不使用它的理由。可以这样使用defined
:
class aaa {
if ! defined(Notify['xxx']) {
notify { 'xxx': message => 'yyy' }
}
}
class bbb {
if ! defined(Notify['xxx']) {
notify { 'xxx': message => 'yyy' }
}
}
include aaa
include bbb
这样,只有当资源不存在时,才会将资源添加到目录中。