Puppet:仅在需要将软件包安装到最新版本时复制文件

时间:2017-06-13 04:05:05

标签: puppet redhat

我是木偶初学者 - 所以忍受我:) 我正在尝试编写一个执行以下操作的模块:

  • 检查是否在repos中安装了最新版本的软件包
  • 如果需要安装软件包,则配置文件将从puppet源位置复制到客户端。然后将安装包
  • 复制文件并安装软件包后,运行将使用客户端上的配置文件的脚本来应用必要的设置。
  • 完成所有这些操作后,删除客户端上复制的文件

我想出了以下内容:

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,
  }
}

虽然这实现了我想要做的大部分工作,但我注意到在重新运行木偶时应用文件,尽管它们被删除,但正在重新进行。

我可以理解为什么会发生这种情况,但我不知道如何对其进行编码,以便只有在更新/安装软件包(例如软件包未安装或旧版本)时才会复制文件。否则每次木偶每30分钟运行一次(默认设置),我会假设...文件将被反复复制...我尝试使用replace => false来防止这种情况,但这只是意味着文件不会得到在第一次运行类之后从/var/tmp中删除,因为它只会阻止类的后续运行重新复制文件(从我的测试中)。这确实可以防止冗余的重复复制 - 但是我只是想让文件第一次消失!

这可能吗?头疼:(

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

编辑:要清楚,这是我正在努力的一点:资源file { 'Package Setup Files':。即使没有更新/安装软件包,这也会继续复制文件。我该如何防止这种情况发生?

1 个答案:

答案 0 :(得分:2)

以下是一些建议。

1)建议短期解决方案

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

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

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

2)考虑一个编排框架

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

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

这有几个原因。

Puppet是一个声明性配置管理系统;你的Puppet代码应该定义一个结束状态。 Puppet与shell脚本不同,在这里,您可以定义以“一步一步”的方式更改服务器状态的步骤,而不是结束状态。

ensure => latest的第一个问题是哲学上的。 latest未定义单个结束状态。代码在时间X的行为与时间Y的行为不同。所以你的代码不是幂等的。

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

因此,既然您需要一个专门的工具来管理版本更新,那么在两个工具的角色之间划清界限就更清晰了:总是使用Puppet来管理配置和初次安装;然后始终使用其他工具来管理更新。

好的,太好了。我在你的评论中看到你已经拥有一台Red Hat Satellite服务器,并且你写了:

  

......卫星内的一些主机有一个旧版本的   百胜之内的软件。但我们不会更新此软件   经常.....也许每年一次。

所以,听起来你在这里使用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'],
  }
}