如何在一次Puppet运行中使用插入的文件更新ERB模板?

时间:2018-10-21 15:27:28

标签: templates dependencies puppet erb

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

通过示例最容易看到这一点:

# 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进行更新非常重要。

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

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

1 个答案:

答案 0 :(得分:3)

  

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

木偶戏分为三个主要阶段:

  1. 事实收集
  2. 目录构建
  3. 目录应用程序

在清单建立阶段会完全评估人偶清单,包括评估所有模板和函数调用。此外,通过主服务器/代理程序设置,目录构建在主服务器上进行,因此在该阶段是“本地系统”。所有目标系统的修改都在目录应用阶段进行。

因此,您的

  $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变量的值。