在 Puppet 中复制之前检查目录是否存在

Checking if a directory exists before copying in Puppet

我试图通过将子目录复制到其他位置来在删除父目录之前获取子目录的备份。

我是这样做的:

exec { "install_path_exists":
  command => "/bin/true",
  onlyif  => "/usr/bin/test -d ${install_path}",
  path    => ['/usr/bin','/usr/sbin','/bin','/sbin'],
}
file { "server_backup_dir" :
  ensure  => 'directory',
  path    => "${distribution_path}/backup/server",
  recurse => true,
  source  => "file:///${install_path}/repository/deployment/server",
  require => Exec["install_path_exists"],
}

Exec 检查目录是否存在,如果存在则return为真。如果目录存在,"server_backup_dir" 文件资源需要 "install_path_exists" 执行 return true。

当目录不存在,并且 "install_path_exists" returns false 时,"server_backup_dir" 仍然执行,并产生以下错误。

Error: /Stage[main]/Is/File[server_backup_dir]: Could not evaluate: Could not retrieve information from environment production source(s) file:////usr/local/{project_location}/repository/deployment/server

我的方法有什么问题,我该如何解决?提前致谢。

我将把它分成两部分,问题是什么,以及如何解决。


What is wrong with my approach ...

您误解了 'require' 行和 Puppet 中关系的性质,以及 Puppet 如何使用在 Exec 中执行的命令的 return 代码。

当您使用所谓的四个 metaparameters for relationships in Puppet - those being: require, before, subscribe & notify - you tell Puppet that you want the application of one resource to be ordered in time in relation to another. (Additionally, the 'subscribe' and 'notify' respond to refresh events 中的任何一个时,但这与此处无关。)

因此,当 Puppet 应用从您的代码构建的目录时,它会首先应用 Exec 资源,即执行 /bin/true 命令,当且仅当安装路径存在时;然后它会二次管理 server_backup_dir 文件资源。另请注意,无论是否实际执行了 Exec 命令,它都会应用 File 资源;唯一的保证是 /bin/true 永远不会 运行 文件资源之后。

此外,Exec 中命令的 return 代码与您预期的功能不同。作为 /bin/true 命令 returns 的退出状态 0 仅告诉 Puppet 允许配置继续;将其与执行命令 return 非零退出状态进行比较,这将导致 Puppet 因错误而停止执行。

下面是一个简单的演示:

▶ puppet apply -e "exec { '/usr/bin/false': }"
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.08 seconds
Error: '/usr/bin/false' returned 1 instead of one of [0]
Error: /Stage[main]/Main/Exec[/usr/bin/false]/returns: change from 'notrun' to ['0'] failed: '/usr/bin/false' returned 1 instead of one of [0]
Notice: Applied catalog in 0.02 seconds

有关详细信息,请仔细阅读我上面链接的页面。在 Puppet 中了解关系和排序通常需要一些时间。


how can I fix this?

您通常会像这样使用 custom fact

# install_path.rb

Facter.add('install_path') do
  setcode do
    Facter::Core::Execution.execute('/usr/bin/test -d /my/install/path')
  end
end

然后在您的清单中:

if $facts['install_path'] {
  file { "server_backup_dir" :
    ensure  => 'directory',
    path    => "${distribution_path}/backup/server",
    recurse => true,
    source  => "file:///my/install/path/repository/deployment/server",
  }
}

查阅文档以获取有关在代码库中编写和包含自定义事实的更多信息。

注:

我最后注意到您在 source 参数中重复使用了 $install_path。如果您的要求是拥有安装路径到分发路径的映射,您还可以构建一个 structured fact。但是,在不知道你到底想做什么的情况下,我不确定你会如何写这篇文章。