Puppet:仅当需要安装最新包时才复制文件

Puppet : Copy files only IF the package needs to be installed to the latest

我是木偶初学者 - 请耐心等待 :) 我正在尝试编写一个执行以下操作的模块:

我得出以下结论:

class somepackage(
  $package_files_base = "/var/tmp",
  $package_setup      = "/var/tmp/package-setup.sh",
  $ndc_file           = "/var/tmp/somefile.ndc",
  $osd_file           = "/var/tmp/somefile.osd",
  $nds_file           = "/var/tmp/somefile.nds",
  $configini_file     = "/var/tmp/somefile.ini",
  $required_files     = ["$package_setup", "$ndc_file", "$osd_file",  $nds_file", "$configini_file"])
{
  package { 'some package':
    ensure  => 'latest',
    notify  =>  Exec['Package Setup'],
  }

  file { 'Package Setup Files':
    path    => $package_files_base,
    ensure  => directory,
    replace => false,
    recurse => true,
    source  => "puppet:///modules/somepackage/${::domain}",
    mode    => '0755',
  }

  exec { 'Package Setup':
    command     => "$package_setup",
    logoutput   => true,
    timeout     => 1800,
    require     => [ File['Package Setup Files']],
    refreshonly => true,
    notify      => Exec['Remove config files'],
  }

  exec { 'Remove config files':
    path        => ['/usr/bin','/usr/sbin','/bin','/sbin'],
    command     => "rm \"${package_setup}\" \"${ndc_file}\" \"${osd_file}\" \"${nds_file}\" \"${configini_file}\"",
    refreshonly => true,
  }
}

虽然这实现了我想做的大部分事情,但我注意到在重新运行ning puppet apply 文件时,虽然它们已被删除,但正在重新复制。

我能理解为什么会发生这种情况,但我不知道如何对其进行编码,以便只有在包 updated/installed(例如,包未安装或旧包)时才会复制文件。否则文件将在我假设的客户端上每 30 分钟(默认设置)每次人偶 运行s 一次又一次地被复制......我尝试使用 replace => false 来防止这种情况但这只是意味着在 class 的第一个 运行 之后,文件永远不会从 /var/tmp 中删除,因为它只会阻止 class 的后续 运行 重新复制文件(来自我的测试)。这确实防止了冗余、重复的复制——但是我只想第一次就删除文件!

这可能吗?头疼:(

提前致谢!我们在 EL7.3 上 运行ning Puppet 版本 3.8.6。

编辑:明确地说,这是我正在努力解决的问题:资源 file { 'Package Setup Files':。即使包不是 updated/installed,这也会不断地复制文件。我该如何防止这种情况发生?

这里有一些建议。

1) 短期解决方案的建议

如果不需要,请停止尝试清理这些文件。将它们放入 /opt 并忘记它们。更好的是,让 Puppet 在其中放置一个 README 文件,这将向您未来的自己和您的管理员同事解释他们是什么以及为什么他们在那里。

虽然我完全理解清理的愿望,但您需要权衡在某个目录中放置一些旧文件的成本与在 Puppet 代码中包含对任何人都没有任何意义的复杂逻辑的成本几个月后。

这就是我会做的,根据我的经验,这也是大多数 Puppet 模块作者对这些类型的设置文件所做的。

2) 考虑编排框架

也就是说,在我看来,您正在尝试使用 Puppet 来执行操作任务,虽然它可以执行操作任务(通过 ensure => latest 等功能),但它确实旨在配置管理工具。

我建议人们使用 Puppet 来 ensure => installed 包(如果您需要完全重建节点,请确保 Puppet 可以正确安装应用程序);然后委托在 Puppet 之外应用版本升级和修补程序等问题。

这有几个原因。

Puppet 是一个声明式配置管理系统;你的 Puppet 代码应该定义一个结束状态。 Puppet 不像 shell 脚本,您可以在脚本中定义强制更改服务器状态的步骤,而不是最终状态,"one step at a time".

ensure => latest 的第一个问题是哲学问题。 latest 没有定义单一的结束状态。您的代码在时间 X 的行为与时间 Y 的行为不同。因此您的代码不是幂等的。

第二个问题是实际问题。您永远无法使用 Puppet 以一般方式解决 RPM 更新问题,因为 Puppet 永远无法了解您系统中的所有 RPM 及其依赖项。因此,不管怎样,您仍然需要一个专门的工具来管理版本更新。

因此,由于无论如何您都需要一个专门的工具来管理版本更新,所以在两个工具的角色之间划清界限会更清晰:始终使用 Puppet 来管理 配置和初始安装;然后始终使用其他工具来管理更新。

好的,很好。我在您的评论中看到您已经拥有一个 Red Hat Satellite 服务器,并且您写道:

...some hosts within the Satellite have got an older version of the software within yum. But we don't update this software very often.....maybe once every year.

所以,听起来您在这里使用 Puppet 来解决您使用 Satellite 的方式中的问题。是否可以通过修正您使用 Satellite 的方式来解决这个问题?如果是这样,我认为那会更干净。

当然,有时正确的做法是使用变通方法,这就是我提供其他一些选项的原因。

3) 如果你真的想让 Puppet 清理那些文件

也许将逻辑移到 shell 脚本中。类似于:

class somepackage {

  $shell =

'#!/bin/bash

# maybe use wget instead of puppet to get the files
wget http://a.b/c.tgz
tar zxf c.tgz

# install stuff

# clean up stuff
'

  file { '/usr/local/bin/installer.sh':
    ensure  => file,
    mode    => '0755',
    content => $shell,
  }

  package { 'some package':
    ensure => latest,
    notify => Exec['installer'],
  }

  exec { 'installer':
    command     => '/usr/local/bin/installer.sh',
    refreshonly => true,
    require     => File['/usr/local/bin/installer.sh'],
  }
}