Puppet 使用 2 个不同的命令安装 DS,并且仅当

问题描述

我对 Puppet 的经验不是很丰富,我真的需要你的帮助。

我有 2 个服务器需要安装 DS(编辑。目录服务器)。运行没有错误,但在服务器中没有运行这些命令。我做错了什么?

exec { 'Install first DS':
    command     => "setup  --serverId first-ds --deploymentKeyPassword ${prof_ds::constants::deployment_pwd} --deploymentKey ${prof_ds::constants::deployment_key} --rootUserDn ${prof_ds::constants::admin_user}  --rootUserPassword ${prof_ds::constants::admin_pwd} --monitorUserPassword ${prof_ds::constants::monitor_pwd} --hostname ${::fqdn} --ldapPort ${prof_ds::constants::ldap_port} --ldapsPort ${prof_ds::constants::ldaps_port} --httpsPort ${prof_ds::constants::https_port} --adminConnectorPort ${prof_ds::constants::admin_port} --replicationPort ${prof_ds::constants::replication_port}  --start  --acceptLicense",onlyif      => ['test "${::fqdn}" == "${ds_hosts[0]}" && echo 0 || echo 1'],environment => ["JAVA_HOME=${java_home}"],path        => ['/usr/bin','/usr/sbin','/bin','/opt/opendj','/opt/opendj/bin'],}

exec { 'Install second DS':
    command     => "setup  --serverId second-ds --deploymentKeyPassword ${prof_ds::constants::deployment_pwd} --deploymentKey ${prof_ds::constants::deployment_key} --rootUserDn ${prof_ds::constants::admin_user} --rootUserPassword ${prof_ds::constants::admin_pwd} --monitorUserPassword ${prof_ds::constants::monitor_pwd} --hostname ${::fqdn} --ldapPort ${prof_ds::constants::ldap_port} --ldapsPort ${prof_ds::constants::ldaps_port} --httpsPort ${prof_ds::constants::https_port} --adminConnectorPort ${prof_ds::constants::admin_port} --replicationPort ${prof_ds::constants::replication_port} --bootstrapReplicationServer ${ds_hosts[0]}:${prof_ds::constants::replication_port} --start --acceptLicense",onlyif      => ['test "${::fqdn}" == "${ds_hosts[1]}" && echo 0 || echo 1'],}

解决方法

我认为您的命令是正确的。所以可能需要修复的是 onlyif 命令,这意味着 exec 命令将被运行 onlyif 它将返回一个非零输出 (more)。该命令将运行,并且在使用双引号时将 interpolate,如果使用单引号则不会运行(是 Ruby 标准而不是 Puppet)

完整代码:

if $::hostname == $ds_hosts[0] {
  exec { 'setup first-ds':
    command     => "setup  --serverId first-ds --deploymentKeyPassword ${prof_ds::constants::deployment_pwd} --deploymentKey ${prof_ds::constants::deployment_key} --rootUserDn ${prof_ds::constants::admin_user}  --rootUserPassword ${prof_ds::constants::admin_pwd} --monitorUserPassword ${prof_ds::constants::monitor_pwd} --hostname ${::fqdn} --ldapPort ${prof_ds::constants::ldap_port} --ldapsPort ${prof_ds::constants::ldaps_port} --httpsPort ${prof_ds::constants::https_port} --adminConnectorPort ${prof_ds::constants::admin_port} --replicationPort ${prof_ds::constants::replication_port}  --start  --acceptLicense",onlyif      => ["test '${::fqdn}' == '${ds_hosts[0]}' && echo 0 || echo 1"],environment => ["JAVA_HOME=${java_home}"],path        => ['/usr/bin','/usr/sbin','/bin','/opt/opendj','/opt/opendj/bin'],}
}

if $::hostname == $ds_hosts[1] {
  exec { 'setup second-ds':
    command     => "setup  --serverId second-ds --deploymentKeyPassword ${prof_ds::constants::deployment_pwd} --deploymentKey ${prof_ds::constants::deployment_key} --rootUserDn ${prof_ds::constants::admin_user} --rootUserPassword ${prof_ds::constants::admin_pwd} --monitorUserPassword ${prof_ds::constants::monitor_pwd} --hostname ${::fqdn} --ldapPort ${prof_ds::constants::ldap_port} --ldapsPort ${prof_ds::constants::ldaps_port} --httpsPort ${prof_ds::constants::https_port} --adminConnectorPort ${prof_ds::constants::admin_port} --replicationPort ${prof_ds::constants::replication_port} --bootstrapReplicationServer ${ds_hosts[0]}:${prof_ds::constants::replication_port} --start --acceptLicense",onlyif      => ["test '${::fqdn}' == '${ds_hosts[1]}' && echo 0 || echo 1"],}
}

更新: 我推荐的另一个优化是通过在前面添加另一个字符来避免测试空字符串(取决于操作系统/版本),例如x

test 'x${::fqdn}' == 'x${ds_hosts[0]}' && echo 0 || echo 1

更新: 详细了解如何以非常简单的经验方式限制特定节点 (more) 上的 exec(也更新了上面的代码片段)

然而,在特定节点上限制特定执行的正确方法是拥有 2 个节点组:Directory Service PrimaryDirectory Service Secondary,将每个节点固定到其对应节点,并使用 resource collector在不同节点上分发工作的功能。

另一个注意事项是您应该避免使用 exec 资源,因为它们不是幂等的。如果这是不可能的,定义一个类型来包装该资源并管理其所有生命周期。在你的情况下会是这样的:

directory_service { 'first-ds':
  deploymentKeyPassword => '?',deploymentKey => '?',}

当您了解要如何管理 DS 服务的配置时,这可能会在以后出现。要获得灵感,请查看 apache。在查看 DS 的 forge 时,有一个模块引起了我的注意:markt-de/puppet-ds_389

,

你的 onlyif 属性在几个层面上都是无稽之谈。您的另一个答案指出了其中一些,但为了完整性:

  • Execonlyif 属性应该是单个命令,作为字符串。您可能通过字符串化您实际呈现的数组很幸运,但您确实应该使它们成为普通字符串。

  • 通过将 onlyif 命令放在单引号中,可以防止 Puppet 为其中的 Puppet 变量引用插入值。

  • 您似乎认为是 onlyif 命令的标准输出决定是否运行主命令,但这是错误的:它是 onlyif' s 退出状态

  • 由于所有被测试的细节在目录构建过程中都是已知的,所以使用 onlyif 属性完全没有意义。 Puppet 条件语句更适合。

  • 但是您应该使用 unlessonlyifcreates 是为了防止在软件已经安装的情况下再次安装该软件.

总的来说,你想要更像这样的东西:

  if $::fqdn == $ds_hosts[0] {
    exec { 'Install first DS':
      command     => "setup  --serverId first-ds ...",unless      => "exit_with_status_0_if_DS_is_already_installed",}
  } elsif $::fqdn == $ds_hosts[1] {
    exec { 'Install second DS':
      command     => "setup  --serverId second-ds  ...",}
  }