由标题数组定义的资源是否始终按顺序进行评估



在Puppet中,可以使用标题数组定义许多资源,如下所示:

file { ['/some/file1', '/some/file2']:
ensure => file,
}

申请顺序而言,是否与以下内容相同?

file { '/some/file1':
ensure => file,
}
-> file { '/some/file2':
ensure => file,
}

我使用的是木偶版本3.8.7,尽管我很好奇这种行为是否在木偶3/4/5之间发生变化。

我已经广泛搜索了文档,虽然他们确实谈论使用一系列标题定义资源,但他们没有谈论这些资源的应用顺序。

这是一个很难回答的复杂问题,但我会将问题分成几个组件来帮助解释。

此资源数组是否对 Puppet 中的典型行为进行排序?

是的。为了帮助解决这个问题,我们需要深入研究Puppet DSL。由于数组是 Puppet DSL 的非对称语法树部分的一部分(通常适用于大多数(如果不是全部)DSL),我们需要检查 Puppet 解析器的相关 AST 代码。在撰写本文时,提交代码在此处。您可以更改链接以指向您的版本,以查看代码如何以及是否已更改,以查看您在任何给定时间使用的 Puppet 版本的行为。

我们要检查的代码是:

# Second level of implicit iteration; build a resource for each
# title.  This handles things like:
# file { ['/foo', '/bar']: owner => blah }
resource_titles.flatten.map do |resource_title| # <-- line of iterator
exceptwrap :type => Puppet::ParseError do
...
if resource.resource_type.is_a? Puppet::Resource::Type
resource.resource_type.instantiate_resource(scope, resource)
end
scope.compiler.add_resource(scope, resource)
scope.compiler.evaluate_classes([resource_title], scope, false) if fully_qualified_type == 'class'
resource
end
end

因此,我们看到资源数组是通过 Ruby 中的Array.map()方法迭代的。这会将特定问题组件转换为"Ruby 中的Array.map()方法是否保留排序?数组中迭代的特定类型是实例化实例时类型代码中指定的标题。这通常是一个符号或字符串,但这里强调的重点是迭代是在简单类型的数组上(即不是嵌套哈希等)。

这个新问题组件的答案也是文档中指定的"是",或者在此链接答案中是简单的"是"。

此资源数组是否对 Puppet 中记录的支持行为进行排序?

不。您可以在此处或此处查看相关文档,并看到没有提及此行为。此外,几年前一位前同事直接向Puppet询问了这个问题,他们的高层回应与我迄今为止在这里概述的相同。

AST 中资源数组的代码可以随时更改,而不会在文档中发出警告,因为这是不受支持的行为。

我应该依赖这种不受支持但似乎总是存在的行为吗?

您的来电。如果这是为了创建嵌套目录之类的事情,那么 Puppet 中的自动require代码无论如何都会捕获任何无序应用资源的问题。如果没有,那么您可能需要对代码清洁度与潜在的未定义行为进行快速的成本/收益计算,通过每次升级时的代码查找以及所述代码查找的时间成本来缓解。

申请顺序而言,是否与以下内容相同?

file { '/some/file1':
ensure => file,
}
-> file { '/some/file2':
ensure => file,
}

与另一个答案">NO">的说法相反,两者并不等同。 另一个答案也没有不同的证明。 它显示的是,在 Puppet 的当前实现中,您的数组样式声明等效于以下内容:

file { '/some/file1':
ensure => file,
}
# no chain operator here
file { '/some/file2':
ensure => file,
}

由于您专门询问应用程序顺序,因此声明的资源之间没有任何显式关系非常重要。

现在,默认情况下,在两个资源之间没有显式关系链的情况下,它们的相对应用顺序将与清单集中的相对评估顺序相同。 但这里有两个重要的警告:

  • 这只是默认设置。 该默认的应用程序顺序规则可以通过Puppet的"排序"设置进行更改。 如果是,则不能依赖基于数组的资源声明来生成与使用链运算符的替代方法相同的应用程序顺序。

  • 默认规则创建的隐式关系可以被显式关系覆盖或规避。 如果在清单集中声明了一个或多个显式关系的相反链,则 Puppet 将使用基于数组的声明接受并遵守它,但在资源声明之间具有显式链运算符的情况下,会拒绝将其作为循环依赖项。

在应用的相对顺序很重要的情况下,必须声明显式关系。 数组标题的资源声明没有这样的语义,但通常,您可以单独添加关系,并且仍然可以获得数组标题的代码清晰度和简洁性优势:

file { ['/some/file1', '/some/file2']:
ensure => file,
}
File['/some/file1'] -> File['/some/file2']

上面有两个有趣的答案是不同意的。我将在这里添加我的 2 美分,并提供一些 OP 可能感兴趣的更多信息。

OP一般询问是否按申请顺序:

file { ['/some/file1', '/some/file2']:
ensure => file,
}

相当于:

file { '/some/file1':
ensure => file,
}
-> file { '/some/file2':
ensure => file,
}

一般来说,答案是否定的,正如约翰所说。

这里有一个简单的演示来证明这一点:

傀儡版:

$ bundle exec puppet -V
5.3.3

我的代码:

# code.pp
include stdlib
$files = range(1, 10).map |$x| { "/tmp/file${x}" }
notice("Files array is: $files")
file { $files:
ensure =>  file,
}

--ordering=random申请:

$ bundle exec puppet apply --ordering=random code.pp 
Notice: Scope(Class[main]): Files array is: [/tmp/file1, /tmp/file2, /tmp/file3, /tmp/file4, /tmp/file5, /tmp/file6, /tmp/file7, /tmp/file8, /tmp/file9, /tmp/file10]
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.05 seconds
Notice: /Stage[main]/Main/File[/tmp/file3]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file9]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file8]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file7]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file1]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file6]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file2]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file4]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file10]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file5]/ensure: created
Notice: Applied catalog in 0.06 seconds

因此,如果没有显式的关系声明,Puppet的随机排序设置会看到随机排序的资源。但是,如果我们在清单中声明了明确的顺序:

# code.pp
file { '/tmp/file1':
ensure => file,
}
-> file { '/tmp/file2':
ensure => file,
}

文件始终按照我们希望的方式排序:

$ for i in {1..5} ; do rm -f /tmp/file* ; bundle exec puppet apply --ordering=random code.pp ; done
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.21 seconds
Notice: /Stage[main]/Main/File[/tmp/file1]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file2]/ensure: created
Notice: Finished catalog run in 0.02 seconds
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.20 seconds
Notice: /Stage[main]/Main/File[/tmp/file1]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file2]/ensure: created
Notice: Finished catalog run in 0.02 seconds
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.23 seconds
Notice: /Stage[main]/Main/File[/tmp/file1]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file2]/ensure: created
Notice: Finished catalog run in 0.02 seconds
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.22 seconds
Notice: /Stage[main]/Main/File[/tmp/file1]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file2]/ensure: created
Notice: Finished catalog run in 0.02 seconds
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.23 seconds
Notice: /Stage[main]/Main/File[/tmp/file1]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file2]/ensure: created
Notice: Finished catalog run in 0.02 seconds

我们还可以使用 Puppet 之前的默认标题哈希排序来获得伪随机排序,其中资源按从资源标题生成的哈希排序:

$ bundle exec puppet apply --ordering=title-hash code.pp 
Notice: Scope(Class[main]): Files array is: [/tmp/file1, /tmp/file2, /tmp/file3, /tmp/file4, /tmp/file5, /tmp/file6, /tmp/file7, /tmp/file8, /tmp/file9, /tmp/file10]
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.05 seconds
Notice: /Stage[main]/Main/File[/tmp/file3]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file6]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file8]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file1]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file4]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file2]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file7]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file10]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file5]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file9]/ensure: created
Notice: Applied catalog in 0.06 seconds

但是如果我们切换到清单排序,我们会再次按数字排序文件:

$ bundle exec puppet apply --ordering=manifest code.pp 
Notice: Scope(Class[main]): Files array is: [/tmp/file1, /tmp/file2, /tmp/file3, /tmp/file4, /tmp/file5, /tmp/file6, /tmp/file7, /tmp/file8, /tmp/file9, /tmp/file10]
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.05 seconds
Notice: /Stage[main]/Main/File[/tmp/file1]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file2]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file3]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file4]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file5]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file6]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file7]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file8]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file9]/ensure: created
Notice: /Stage[main]/Main/File[/tmp/file10]/ensure: created
Notice: Applied catalog in 0.07 seconds

我认为正如约翰所说,Matt的答案是正确的,但只是假设使用了"manifest"的默认顺序;并且还假设没有一个资源自动需要其他资源。

另请参阅Gary Larizza关于订购的帖子 这里.

最新更新