在模块中,使用定义的资源在 puppet3 中有效,但在 puppet5 中失败

In a module, using a defined resource works in puppet3, but fails in puppet5

所有内容都在 manifests 目录中。

在清单 execute.pp 中,我有:

define execute (
   String $command         = "echo",
   String $workdirectory   = "/tmp",
   String $runas           = "www",
   Boolean $failonerror    = true  
) {
    # Resources
    require stdlib
    etc ...

使用它的代码:

 ....
 if defined(Execute["$titlePreviousExecRes"]) {
 ....

puppet5 的错误是

Error: Evaluation Error: Error while evaluating a Resource Statement, Evaluation Error: Resource type not found: Execute at ...

你定义的类型的清单在物理上位于模块(你没有透露其名称)的清单中,但该类型不是模块的一部分,因为它的名称不在模块的命名空间中。因此,Puppet 的加载程序将找不到它。您的代码对于 Puppet 3 来说也有问题,但它似乎受益于融合和松散特性。

例如,如果您定义的类型应该属于名为 "mymodule" 的模块,那么它应该在该命名空间中显式声明:

define mymodule::execute ( ...

它也应该通过该命名空间引用

if defined(Mymodule::Execute["$titlePreviousExecRes"]) {

。通过将您定义的类型放在正确的命名空间中并通过其完全限定名称引用它来解决您的问题。


至于为什么它似乎在 Puppet 3 中有效,Puppet 语言的第 3 版假设引用了 classes 和未明确锚定到顶级范围的类型(例如 ::execute)可能 相对于 的名称空间 class 或引用出现的类型(或什至其他一些)。那么,在您的情况下,自动加载器首先会猜测您对名为 Execute 的类型的引用可能是为了引用 ::mymodule::execute。看到清单 mymodule/manifests/execute.pp 存在,它将评估该文件,从而获得类型 ::execute 的定义 - not::mymodule::execute 它是正在寻找。

如果没有找到它正在寻找的类型,自动加载器将在其他命名空间中搜索,直到最终尝试顶级范围。然而,当它到达那里时,它会发现它已经拥有从模块中的清单中获得的顶级范围定义,因此加载程序会成功,提供那个放错地方的定义。但这仅适用于同一模块内的引用,并且存在严重的冲突风险。

Puppet 5 的自动加载器仍然表现出一些用于定位 class 和定义的类型定义的回退行为,但 Puppet 不再识别相对的 class 和定义的类型名称。因此,当尝试解析您对类型 execute 的引用时,自动加载器从不考虑评估 mymodule/manifests/execute.pp,因为这是它期望找到 ::mymodule::execute 的地方,而不是它正在寻找的类型 ::execute.

因此,不,您的定义永远不会被定位或加载。这是一个功能,不是错误。