"::mysql::server" 和 "mysql::server" 之间的区别

Difference between "::mysql::server" and "mysql::server"

我正在检查一个旧的木偶代码。它使用 mysql puppet 模块来安装 mysql-server。

我遇到了这个

class { '::mysql::server':

}

还有这个

class { 'mysql::server':
}

现在我很困惑。它们是同一个意思还是两者有什么区别?

这真是个好问题。简短的回答是它们是相同的,class 名称不需要 ::

我一直认为需要初始 :: 来避免范围歧义(其中 class foo 中的 include bar 将包括 ::foo::bar 而不是::bar) 但是查看文档,他们说,例如,include 必须使用 class 的全名。

一个工作示例:

$ cat scope.pp
class foo {
  class bar {
    notice("foo::bar")
  }
  class { 'bar':
  }
}

class bar {
  notice("bar")
}

class { 'foo':
}
$ puppet apply scope.pp
Notice: Scope(Class[Bar]): bar

我会注意到,虽然这对于 class 范围是正确的,但对于 Puppet 中的变量范围肯定不是这样,如下所示。

$ cat var_scope.pp
$bar = "bar"

class foo {
  $bar = "foo::bar"
  notice($::bar)
  notice($bar)
}

include foo
notice($bar)
$ puppet apply var_scope.pp
Notice: Scope(Class[Foo]): bar
Notice: Scope(Class[Foo]): foo::bar
Notice: Scope(Class[main]): bar

Do they both mean the same thing or there's any difference between the two?

TL;DR:它们对 classes 和定义的类型意味着相同的事情。支持具有前导 :: 的形式可以被视为向后兼容功能、内部一致性功能或两者兼而有之。但是,对于变量,前导 :: 表示顶级范围变量,如果您使用裸变量名称,它可能是也可能不是您得到的。


为了澄清@Jon 已经给出的正确答案的一些细节,我们必须考虑 Puppet 版本 3 及更早版本的行为。这不再记录在 Puppet 的主要文档站点上,但我们可以在 Puppet 的 online archive of obsolete documentation. Specifically, we want to look at Puppet namespaces and their behavior. The docs are an interesting read if you're into that sort of thing, especially the historical perspective 中找到相关文档,了解 Puppet 3 如何结束它的位置,但这里有一个有点异想天开的事件版本:

一开始,熔炉是空无一物的,没有模块。每个人什么都写自己的代码,devops 忠实者被深深地压迫,重新发明了很多轮子。

那时候萌生了模块的想法。当时的模块是利用当时国外的功能构建的,例如 import 功能,此后已消失。但是代码共享带来了名称冲突,对此,人们以命名空间作为回应。 Reductive Labs 研究了命名空间,发现它很好。

但并不是 Reductive 或人们都清楚,在无知的情况下,Reductive 带来了相对名称解析。相对名称解析非常深入地审查了名称和命名空间,甚至试图解析相对于范围内每个命名空间的限定名称。一些人为这方便而高兴,但他们中的智者很快就感到不安。他们很清楚,相对名称解析看得太深了,看得太多了。它有时会看到不该看到的东西,并为信徒开辟了错误的道路。

所以智者介入了。他们宣称相对命名空间应该被束缚和克服,通过只给它提供锚定到一个真正的匿名命名空间的名字来驯服它,这个匿名命名空间先于任何其他 Puppet 存在。束缚的形式是领先的双冒号,::。尽管相对名称解析经常不受束缚地执行相同的工作,但许多人听取了智者的意见,并因此受到赞扬。

而 Reductive,随后将自己命名为 Puppet Labs,对创建相对名称解析感到遗憾,并敦促人们听从智者的建议。但是当它出现傀儡第三纪元的时候,它不能给那些不在意的人带来麻烦,所以它允许相对名称解析存在。

但是在第四纪元的黎明,不再是实验室的 Puppet 找到了最终杀死相对名称解析的勇气,而且它不再存在了。从那天起,Puppet 不再敦促 classes 和类型的提供者和用户使用领先的双冒号,但它尊重过去智慧的遗产,并对那些缓慢忘记它的人表示同情。

然而 Puppet 出于仁慈,从所有命名事物中选择 class 变量作为唯一具有两个名称的变量。它们具有超越名称空间的作用域,并且在它们的作用域中它们可以通过它们定义的简单名称而为人所知。然而,就像所有命名的事物一样,它们可以通过它们的命名空间名称在任何地方被人所知,这些名称由它们的简单名称和它们的 class 名称组成,可以是任何一种形式。但是,顶级作用域的变量是什么?当他们隐藏在阴影中时,他们可以知道什么名字?在这里,领先的双冒号仍然有效。它的顶级范围标记对于变量来说并不是多余的,并且一些聪明人通过始终对此类变量使用它来使他们的代码清晰。