【问题标题】:Puppet 4: how to add calling class variables to scope of a defined typePuppet 4:如何将调用类变量添加到定义类型的范围
【发布时间】:2017-02-27 15:30:22
【问题描述】:

在 Puppet 3 和之前的版本中,模板从调用类定义继承范围的方式与本机定义类型的方式相同,因此,如果我有一个文件资源,其中包含由定义创建的模板源,则该模板可以使用变量集在调用类中,无论哪个类调用了define。

在 Puppet 4 中(也使用 Puppet 3.8 未来解析器进行了测试),这似乎不再是这种情况,并且它导致在我的环境中甚至难以测量的损坏,我的环境依赖这种行为数以万计的代码行。有什么办法可以把它找回来吗?经过研究,即使将定义转换为本机类型也不能解决问题,因为它们依赖于收集服务器端信息的能力,这些信息包括通过自定义函数在不同模块中可用的模板,以及本机资源类型中的所有内容似乎发生在客户端上。

这是可以修复的,还是我尝试等待 Puppet 5?

编辑:这里不要太拘泥于“范围”这个词——我需要任何方法将所有类变量传递给一个定义并在那里解压它们,以便它们可用于模板,或者有一种方法原生类型查看 puppetmaster 上指定模块内的文件。只要有这个结果,我就会接受任何奇怪、晦涩的消息传递选项,因为类不知道模板在哪里——只有定义知道,因为它使用了辅助函数扫描服务器上的文件系统。

编辑 2:要证明这在 Puppet 3.8.5 中按预期工作,请使用以下内容:

modules/so1/manifests/autotemplate.pp:

# Minimal define example for debugging
define so1::autotemplate (
    $ensure = 'present',
    $module = $caller_module_name,
) {
    $realtemplate = "${module}${title}"

    file { $title :
        ensure  => $ensure,
        owner   => 'root', group => 'root', mode => '0600',
        content => template($realtemplate),
    }
}

在模块/so2/manifests/example.pp:

# Example class calling so1::autotemplate
class so2::example (
    $value = 'is the expected value'
) {
    so1::autotemplate { '/tmp/qwerasdf': }
}

在模块/so2/templates/tmp/qwerasdf:

Expected value: <%= @value %>

在关闭未来解析器的 Puppet 3.8.5 中,这会导致在系统上生成 /tmp/qwerasdf,其内容如下:

Expected value: is the expected value

在 Puppet 3.8.5 中。使用 environment.conf 中的parser = future(还有 Puppet 4.x,尽管我专门在 3.8.5 未来的解析器环境中测试了这个示例),这会导致文件的内容被创建:

Expected value:

编辑 3:精确的两个字修饰

【问题讨论】:

  • 人们无法避免关注“范围”,因为这不仅是您使用的词,而且是您正在讨论的概念的正确词。因此,您的编辑似乎试图改变问题以提出与以前大不相同的问题。冒着听起来自私自利的风险,您不应该在收到答复后这样做。
  • 问题是标题中的问题——如何将所有调用类变量添加到已定义类型的范围内。其余的只是背景——在 Puppet 3 中,这是自动发生的,一直到 3.8.5。我不需要它在 Puppet 4 中是自动的——我只需要它是可能的
  • 标题中问题的答案还是我写的(更新后的)。 Puppet 3 中定义的类型从不从 using 类的作用域中获取变量。模板确实如此,但这是一个错误,尽管仅在 Puppet 4 中修复了一个错误,并且在 Puppet 3 中启用了未来的解析器时。您可以通过定义类型的参数将数据从调用类传递给定义的类型,并且模板可以访问通过其scope 对象从外部范围获取数据。没有理由认为这会在 Puppet 5 中发生变化。

标签: puppet


【解决方案1】:

在 Puppet 3 和之前的版本中,从调用类定义继承范围的方式与原生定义类型的方式相同,因此,如果我有一个文件资源,其中包含由定义创建的模板源,则该模板可以使用在调用类,无论哪个类调用了定义。

您所描述的是 Puppet 的旧动态范围。范围规则的变化是 Puppet 3.0 的主要变化之一;它在 Puppet 4 中并不新鲜。但是,在 Puppet 3 中,a bug 模板仍然使用动态范围。这在 Puppet 3.5 中已修复,但只是在预期的情况下 - 即启用未来解析器时。定义类型本身经历了 Puppet 3.0.0 中的范围更改,以及其他所有内容。范围变更在刚开始实施时是一件大事(Puppet 投入了大量精力来提醒用户注意它们),但现在这里没什么大不了的。

它导致的损坏在我的环境中甚至都难以衡量,我的环境依赖于这种行为来处理数万行代码。

很抱歉让您有这种经历。

有什么办法可以找回来吗?

没有。 Puppet 范围规则不会按照您希望的方式工作。他们确实在 Puppet 3 中的模板(但不是大多数其他地方)中以这种方式工作,这与 Puppet 的文档相悖,而且从来都不是故意的。

这是可以修复的,还是我尝试等待 Puppet 5?

没有办法在 Puppet 4 中的模板或其他地方获得动态变量范围,我没有理由认为 Puppet 5 中会有一个。

如果您需要一个模板来扩展特定类范围内的主变量,那么您可以通过在该类的范围内评估模板来获得它。或者,ERB 模板可以从(特定的)其他范围by means of the scope object 获取变量。另一方面,如果您想在已定义类型的范围内扩展模板,则可以考虑将所需的变量作为该类型的参数传递。

可能还有其他方法可以解决您的问题,但我需要更多详细信息才能提出任何其他建议。 (如果您选择在 SO 上提问,这将构成一个单独的问题。)

【讨论】:

  • 同意这是否会再次出现在 Puppet 5 中是值得怀疑的。
  • 查看我的更新。不要太拘泥于作用域的机制——问题实际上是关于如何将每个变量打包到一个类中,以便它们可以显示在定义的范围内。我不在乎它是否按范围,通过晦涩的功能,通过我隐藏在服务器上某处的自定义 ruby​​ 代码发生,只要一个类可以在一行中说“处理此文件”并具有定义工作中的逻辑.
  • 另外,顺便说一句,这段代码绝对可以在 Puppet 3.8.5 上运行,而无需启用未来的解析器。一旦启用未来的解析器,它就会立即中断,或者在 Puppet 4.8.2
  • @Zed,如果您认为我的 cmets 不适用于您的代码,那么我倾向于认为您的代码所做的事情并没有很好地被问题所描述。您的编辑也将我引向了那个方向。如果您的问题确实与范围不同,那么我建议当您再次尝试提出问题时,请附上minimal reproducible example 以帮助澄清您真正想知道的内容。
  • @Zed,你是对的,当未启用未来解析器时,所有版本的 Puppet 3 中都存在错误行为。该修复仅在启用未来解析器时适用。我已经在这方面更新了我的答案。在 Puppet 3 中,模板仍然没有打算使用动态范围,并且在启用未来解析器时它们。这种通用的东西——帮助你为主要版本之间的变化做准备——是未来解析器的目的之一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多