仅在 RPM 更新时复制覆盖文件

问题描述

我的 Puppet 安装有以下问题:

  • 如果安装了新版本的 RPM 包,我只想复制(覆盖)一个文件

我有这样的事情:

    package { 'my-rpm':
      ensure => $version,source => $rpm_file,notify => File[$my_file],}

    file { $my_file:
      ensure  => present,source  => $my_file_template,replace => true,# Overwrite (default behavIoUr). Needed in case new RPM was installed.
    }

问题是,如果没有安装新版本的 RPM,“文件”也会被执行。发生这种情况,因为我之后使用“file_line”更改了 $my_file 文件

    file_line { 'disable_my_service':
      ensure => present,path   => $my_file,line   => '        <deployment name="My.jar" runtime-name="My.jar" enabled="false">',match  => '        <deployment name="My.jar" runtime-name="My.jar">',}

$my_file 内容的这种更改会在每次 Puppet 运行时触发从模板复制新版本。

我可以在我的文件副本定义中添加“repace => false”,但这会破坏任何进一步的更新......

长话短说:我有以下循环

我怎样才能打破这个循环?

更新: 澄清:

  • “file_line”定义可选执行,由 Puppet hiera-property 控制,因此“启用”部分不能包含在 RPM 中。
  • 无法将整个文件转换为模板 (恕我直言)。问题:Puppet 模块必须能够安装文件的不同(未来)版本。
  • 问题暂时没有解决

解决方法

我认为您在这里遇到的问题是您正在尝试使用 filefile_line 资源类型来管理 $my_file,这是将导致文件在目录应用程序期间更改。 选择其中一个,将其作为模板或按文件行进行管理。 我怀疑在 Puppet 运行期间发生的事情是 file 资源更改 $my_file 看起来像这样;

<deployment name="My.jar" runtime-name="My.jar">

因为那是模板中的内容,file_line 资源将其更改为;

<deployment name="My.jar" runtime-name="My.jar" enabled="false">

然后在下一次运行时发生完全相同的事情,file 更改 $my_file 以匹配模板,然后 file_line 更改它以修改该行。

我会删除 notify => File[$my_file], 它实际上并没有做任何事情,您正在代码中定义所需的状态,因此如果该文件因任何原因,手动更改或 RPM 更新而更改,Puppet 会将该文件带回来在运行过程中进入所需的状态。你可能要考虑;

  file { $my_file:
    ensure  => present,source  => $my_file_template,require => Package['my-rpm'],}

这可确保在 package 资源之后强制执行文件所需的状态,因此如果包更改了文件,该文件将在同一次运行中得到纠正。 https://puppet.com/docs/puppet/7.4/lang_relationships.html

您可能还想考虑;

  file { $my_file:
    ensure  => present,notify  => Service['my-service'],}

所以当配置文件改变时,rpm提供的服务会重新启动。

,

仅在 RPM 更新时复制覆盖文件

问题是,如果没有安装新版本的 RPM,“文件”也会被执行。发生这种情况,因为我之后使用“file_line”更改了 $my_file 文件

是的,每次运行都会应用节点目录中的 File 资源。事实上,最好的观点是每个 将其放入节点目录中的资源在每次运行时都会应用。资源的属性会影响应用它们的意义和/或它们同步的意义,而不是它们是否被应用。例如,在 File 的情况下,设置 replace => false 表示只要文件最初存在,其内容就是同步的(因此不应修改),而 replace => true 表示仅当文件内容与指定的 sourcecontent 完全匹配时才同步。

一般来说,通过多个 Puppet 资源管理相同或重叠的物理资源效果不佳,这就是您在这里遇到的问题。当您遇到问题时,最惯用的方法通常是编写自定义资源类型来详细管理目标对象。但在本例中,您似乎可以通过使用 Exec 执行一次性更新后复制来解决此问题:

    package { 'my-rpm':
      ensure => $version,source => $rpm_file,}

    ~> exec { "Start with default ${my_file}":
      command => "cp '${my_file_template}' '${my_file}'",# this is important:
      refreshonly => true,}

    -> file { $my_file:
      ensure  => 'file',replace => false,# no source or content
      owner   => 'root',# or whatever
      group   => 'root',# or whatever
      mode    => '0644',# ...
    }

    -> file_line { 'disable_my_service':
      ensure => present,path   => $my_file,# ...
    }

当然,如果您愿意或有需要,您可以使用关系元参数而不是链接箭头。

这种方法为您提供:

  • 通过包管理器管理包;
  • 仅在更新包触发时才将打包的默认文件复制到目标文件(通过 Puppet - 如果手动更新包,您将无法获得此信息);
  • 通过File资源管理文件内容以外的属性;和
  • 通过 File_line 资源管理文件内容的特定行。