Puppet 由标题数组定义的资源是否总是按顺序计算?

Puppet 由标题数组定义的资源是否总是按顺序计算?,puppet,Puppet,在Puppet中,可以使用标题数组定义大量资源,如下所示: file { ['/some/file1', '/some/file2']: ensure => file, } 就申请顺序而言,是否与以下相同 file { '/some/file1': ensure => file, } -> file { '/some/file2': ensure => file, } file { '/some/file1': ensure => file, }

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

file { ['/some/file1', '/some/file2']:
  ensure => file,
}
就申请顺序而言,是否与以下相同

file { '/some/file1':
  ensure => file,
}
-> file { '/some/file2':
  ensure => file,
}
file { '/some/file1':
  ensure => file,
}
-> file { '/some/file2':
  ensure => file,
}
我使用的是puppet版本3.8.7,不过我很好奇这种行为是否在puppet 3/4/5之间发生了变化


我对文档进行了广泛的搜索,虽然他们讨论了使用一系列标题定义资源,但他们没有讨论这些资源的应用顺序。

这是一个需要回答的复杂问题,但我将把问题分成几个部分来帮助解释

这是Puppet中的典型资源数组排序行为吗

对。为了对此有所帮助,我们需要深入研究傀儡DSL。由于数组是Puppet DSL的非对称语法树部分的一部分,并且通常对于大多数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,
}
file { '/some/file1':
  ensure => file,
}
-> file { '/some/file2':
  ensure => file,
}
与另一个答案的说法相反,不,两者并不等同。另一个答案也没有表现出不同。它显示的是,在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应用:

因此,如果没有明确的关系,decla 配给,傀儡的随机排序设置可以看到随机排序的资源。但是,如果我们在清单中声明了明确的订单:

# 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
我认为正如John所说,Matt的回答是正确的,但前提是使用了清单的默认顺序;并且还假设没有任何资源自动需要其他资源


另请参阅Gary Larizza关于订购的帖子。

恐怕我不同意您的无保留的“是”。我已经在自己的回答中详细说明了我的立场,我同样不同意这一点。虽然支持性陈述基本上是正确的,但我相信你从中得出了错误的结论。那么,@MattSchuchard,你愿意详细说明一下吗?基本的问题是,一个名为resource declaration的数组是否等价于一系列独立的资源声明,其间包含链式运算符。事实并非如此。这两者可以产生不同的编译和应用程序行为顺序——后者是OP特别感兴趣的——这取决于Puppet配置和整个清单集。或者如果你不同意,那么你的依据是什么?好吧,这里有一些实际的相互矛盾的证据。启发式证据,但仍然是证据。我觉得有点恼火,我们可能在这方面被误导了,虽然当时的版本是3.7.2,但我觉得舱单排序在当时并不存在。