首页 > 解决方案 > 如何在一次 Puppet 运行中使用插入的文件更新 ERB 模板?

问题描述

我正在尝试使用 ERB 模板在 Puppet 5 中构建文件。此 ERB 文件以正常方式使用类变量,但也是通过插入另一个 Puppet 管理的本地文件来构造的。但是,我发现每当我更新插入的文件时,都需要运行两次Puppet 才能更新 ERB 生成的文件。我希望在一次Puppet 运行中进行更新。

用一个例子最容易看出这一点:

# test/manifests/init.pp
class test {
  # This file will be inserted inside the next file:
  file { '/tmp/partial.txt':
    source => 'puppet:///modules/test/partial.txt',
    before => File['/tmp/layers.txt'],
  }

  $inserted_file = file('/tmp/partial.txt')
  # This file uses a template and has the above file inserted into it.
  file { '/tmp/layers.txt':
    content => template('test/layers.txt.erb')
  }
}

这是模板文件:

# test/templates/layers.txt.erb
This is a file
<%= @inserted_file %>

如果我对文件进行更改,test/files/partial.txt则需要运行两次Puppet 才能将更改传播到/tmp/layers.txt. 出于操作原因,仅在一次 Puppet 运行中发生更新非常重要。

我尝试过使用各种依赖项(before,require等)甚至 Puppet 阶段,但我尝试的所有操作仍然需要两次 Puppet 运行。

虽然可以使用exec具有(或类似的东西)的资源来实现相同的结果sed,但我宁愿使用“纯”Puppet 方法。这可能吗?

标签: templatesdependenciespuppeterb

解决方案


我正在尝试使用 ERB 模板在 Puppet 5 中构建文件。此 ERB 文件以正常方式使用类变量,但也是通过插入另一个 Puppet 管理的本地文件来构造的。

Puppet 运行分为三个主要阶段:

  1. 事实收集
  2. 目录建设
  3. 目录申请

Puppet 清单在目录构建阶段进行了全面评估,包括评估所有模板和函数调用。此外,通过主服务器/代理设置,目录构建发生在主服务器上,因此在该阶段这是“本地系统”。所有目标系统修改都发生在目录应用阶段。

因此你的

  $inserted_file = file('/tmp/partial.txt')

在目录构建期间运行,之前File[/tmp/partial.txt]应用。由于您提供了file()函数的绝对路径,因此它会尝试使用目录构建系统上已经存在的版本,这甚至不一定是为其构建清单的机器。

我不清楚你为什么要安装和管理除了完整的模板文件之外的部分结果,但如果你确实这样做了,那么在我看来,最好的方法是从同一来源提供两者试图从另一个喂一个。为此,您可以利用该file函数从(任何)模块目录中的文件加载数据的能力files/,类似于如何File.source做。

例如,

# test/manifests/init.pp
class test {
  # Reads the contents of a module file:
  $inserted_file = file('test/tmp/partial.txt')

  file { '/tmp/partial.txt':
    content => $inserted_file,
    # resource relationship not necessary
  }

  file { '/tmp/layers.txt':
    # interpolates $inserted_file:
    content => template('test/layers.txt.erb')
  }
}

另请注意,示例清单中的注释具有误导性。您提供的文件资源和它管理的文件内容都不会插入到您的模板中,除非是偶然的。内插的是$inserted_file评估模板的类的变量的值。


推荐阅读