Puppet 在多个模块中调用相同的服务?
Puppet calls same service in multiple module?
我有一个人偶模块A。
在那个模块中,我有一个服务重新启动以更改文件。
class A::test1 {
include ::corednsclient
service { 'sshd':
ensure => running,
enable => true,
}
}
现在,我有一个不同的人偶模块 B。
在该模块中,我还必须重新启动相同的服务以更改另一个文件。
现在,问题是我得到以下信息:
Duplicate declaration error
当我在做 /opt/puppetlabs/bin/puppet apply --modulepath=/abc xyz/site.pp
如果我独立运行每个模块 puppet apply -e 'include moduleA'
和
puppet apply -e 'include moduleB' ,两者都可以正常工作。
但是 puppet apply global 似乎失败了。
非常感谢任何帮助!
Error: Evaluation Error: Error while evaluating a Resource Statement,
Duplicate declaration: Service[sshd] is already declared in file
/export/content/ucm/puppet/modules/coresshd/manifests/configure.pp:28; cannot
redeclare at
/export/content/ucm/puppet/modules/corednsclient/manifests/daemon_reload.pp:10 at
/export/content/ucm/puppet/modules/corednsclient/manifests/daemon_reload.pp:10:3 on
node lor1-0002276.int.xxx.com .
是的,这是正常的。 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 重构,使两个 class 继承第三个 class
通常,解决此问题的最佳方法是重构您的代码,以便有第三个 class 包含重复的资源,其他 classes include 使用 include
函数,像这样:
class ccc {
notify { 'xxx': message => 'yyy' }
}
class aaa {
include ccc
}
class bbb {
include ccc
}
include aaa
include bbb
效果很好。
请注意,这只有效,因为 include
函数可以调用任意次数,这与资源声明不同 - 也不同于 resource-like class 声明。
您可以阅读更多关于 "include-like v resource-like class declarations" here。
方案二使用虚拟资源
您也可以使用 virtual resources。像这样重构:
class ccc {
@notify { 'xxx': message => 'yyy' }
}
class aaa {
include ccc
realize Notify['xxx']
}
class bbb {
include ccc
realize Notify['xxx']
}
include aaa
include bbb
这个的另一个优点是您可以使用资源收集器和select仅来自一组虚拟资源的特定资源,如下所示:
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 使用确保资源
另一个选项是 stdlib 中的 ensure_resources
函数:
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
这样,只有当目录中没有资源时,才会将资源添加到目录中。
我有一个人偶模块A。 在那个模块中,我有一个服务重新启动以更改文件。
class A::test1 {
include ::corednsclient
service { 'sshd':
ensure => running,
enable => true,
}
}
现在,我有一个不同的人偶模块 B。 在该模块中,我还必须重新启动相同的服务以更改另一个文件。
现在,问题是我得到以下信息:
Duplicate declaration error
当我在做 /opt/puppetlabs/bin/puppet apply --modulepath=/abc xyz/site.pp
如果我独立运行每个模块 puppet apply -e 'include moduleA' 和 puppet apply -e 'include moduleB' ,两者都可以正常工作。 但是 puppet apply global 似乎失败了。
非常感谢任何帮助!
Error: Evaluation Error: Error while evaluating a Resource Statement,
Duplicate declaration: Service[sshd] is already declared in file
/export/content/ucm/puppet/modules/coresshd/manifests/configure.pp:28; cannot
redeclare at
/export/content/ucm/puppet/modules/corednsclient/manifests/daemon_reload.pp:10 at
/export/content/ucm/puppet/modules/corednsclient/manifests/daemon_reload.pp:10:3 on
node lor1-0002276.int.xxx.com .
是的,这是正常的。 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 重构,使两个 class 继承第三个 class
通常,解决此问题的最佳方法是重构您的代码,以便有第三个 class 包含重复的资源,其他 classes include 使用 include
函数,像这样:
class ccc {
notify { 'xxx': message => 'yyy' }
}
class aaa {
include ccc
}
class bbb {
include ccc
}
include aaa
include bbb
效果很好。
请注意,这只有效,因为 include
函数可以调用任意次数,这与资源声明不同 - 也不同于 resource-like class 声明。
您可以阅读更多关于 "include-like v resource-like class declarations" here。
方案二使用虚拟资源
您也可以使用 virtual resources。像这样重构:
class ccc {
@notify { 'xxx': message => 'yyy' }
}
class aaa {
include ccc
realize Notify['xxx']
}
class bbb {
include ccc
realize Notify['xxx']
}
include aaa
include bbb
这个的另一个优点是您可以使用资源收集器和select仅来自一组虚拟资源的特定资源,如下所示:
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 使用确保资源
另一个选项是 stdlib 中的 ensure_resources
函数:
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
这样,只有当目录中没有资源时,才会将资源添加到目录中。