将散列附加到 Puppet4 中的一系列嵌套散列

Chr*_*ner 4 puppet

给定的是 hieradata 中的散列值:

profile::jdbc::connections
  connection_name1:
    username: 'user1'
    password: 'pass1'
  connection_name2:
    username: 'user2'
    password: 'pass2'
Run Code Online (Sandbox Code Playgroud)

以及 puppet 代码中的默认值散列:

$jdbc_default = {  
  'testWhileIdle'                => true,
  'testOnBorrow'                 => true,
  'testOnReturn'                 => false,
  'timeBetweenEvictionRunsMillis'=> '30000',
  'maxActive'                    => '20',
  'maxWait'                      => '10000',
  'initialSize'                  => '5',
  'removeAbandonedTimeout'       => '600',
  'removeAbandoned'              => false,
  'logAbandoned'                 => true,
  'minEvictableIdleTimeMillis'   => '30001',
}
Run Code Online (Sandbox Code Playgroud)

如何将默认值添加到连接哈希中的每个哈希?

结果也可以是一个散列数组,但是一个与连接散列中的键相同的散列会很好。

Ale*_*vey 5

Puppet 4 提供了许多可以在这里使用的迭代函数,但最清晰、最容易理解的解决方案可能是使用 Puppet 的mapmerge函数(refref):

  $connections = {
    'connection_name1' => {
      'username' => 'user1',
      'password' => 'pass1',
    },
    'connection_name2' => {
      'username' => 'user2',
      'password' => 'pass2',
    },
  }

  $jdbc_default = {
    'testWhileIdle'                => true,
    'testOnBorrow'                 => true,
    'testOnReturn'                 => false,
    'timeBetweenEvictionRunsMillis'=> '30000',
    'maxActive'                    => '20',
    'maxWait'                      => '10000',
    'initialSize'                  => '5',
    'removeAbandonedTimeout'       => '600',
    'removeAbandoned'              => false,
    'logAbandoned'                 => true,
    'minEvictableIdleTimeMillis'   => '30001',
  }

  $merged = $connections.map |$k,$v| {
    {$k => merge($jdbc_default, $v)}
  }

  notice($merged)
Run Code Online (Sandbox Code Playgroud)

然后检查一下:

Notice: Scope(Class[main]): [{connection_name1 => {username => user1, password => pass1, testWhileIdle => true, testOnBorrow => true, testOnReturn => false, timeBetweenEvictionRunsMillis => 30000, maxActive => 20, maxWait => 10000, initialSize => 5, removeAbandonedTimeout => 600, removeAbandoned => false, logAbandoned => true, minEvictableIdleTimeMillis => 30001}}, {connection_name2 => {username => user2, password => pass2, testWhileIdle => true, testOnBorrow => true, testOnReturn => false, timeBetweenEvictionRunsMillis => 30000, maxActive => 20, maxWait => 10000, initialSize => 5, removeAbandonedTimeout => 600, removeAbandoned => false, logAbandoned => true, minEvictableIdleTimeMillis => 30001}}]
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.07 seconds
Notice: Applied catalog in 0.01 seconds
Run Code Online (Sandbox Code Playgroud)

但是,您提到您的数据来自 Hiera。因此,您的实际代码如下所示:

class profile::jdbc (
  Hash[String, Hash[String, String]] $connections,
) {
  $jdbc_default = {
    'testWhileIdle'                => true,
    'testOnBorrow'                 => true,
    'testOnReturn'                 => false,
    'timeBetweenEvictionRunsMillis'=> '30000',
    'maxActive'                    => '20',
    'maxWait'                      => '10000',
    'initialSize'                  => '5',
    'removeAbandonedTimeout'       => '600',
    'removeAbandoned'              => false,
    'logAbandoned'                 => true,
    'minEvictableIdleTimeMillis'   => '30001',
  }

  $merged = $connections.map |$k,$v| {
    {$k => merge($jdbc_default, $v)}
  }

  notice($merged)
}
Run Code Online (Sandbox Code Playgroud)

请注意,由于可以在 Puppet 中添加mergeHashes,因此可以避免使用来自 stdlib的函数:

  $merged = $connections.map |$k,$v| {
    {$k => $jdbc_default + $v}
  }
Run Code Online (Sandbox Code Playgroud)

(注意{'a' => 1} + {'b' => 2}return {'a' => 1, 'b' => 2}。如果键在两者中,则右侧获胜,即{'a' => 1, 'b' => 2} + {'a' => 2}return {'a' => 2, 'b' => 2}。)

现在,如果您需要散列的散列,而不是散列的数组,则可以通过以下reduce函数实现:

  $merged = $connections.reduce({}) |$memo, $x| {
    $memo + {$x[0] => merge($jdbc_default, $connections[$x[0]])}
  }
Run Code Online (Sandbox Code Playgroud)

或者:

  $merged = $connections.reduce({}) |$memo, $x| {
    $memo + {$x[0] => $jdbc_default + $connections[$x[0]]}
  }
Run Code Online (Sandbox Code Playgroud)

这是如何工作的:

reduce迭代[key, value]哈希中的每一对。起始值是{}作为参数传递给 的空哈希reduce

在第一轮中,$memo设置为{},并且$x设置为第一[key, value]对。因此,密钥由 给出$x[0]

在随后的轮次中,$memo保留上一次迭代中Lambda中的表达式返回的值,即$memo + {$x[0] => $connections[$x[0]] + $jdbc_default}

展示这个作品:

Notice: Scope(Class[Profile::Jdbc]): {connection_name1 => {username => user1, password => pass1, testWhileIdle => true, testOnBorrow => true, testOnReturn => false, timeBetweenEvictionRunsMillis => 30000, maxActive => 20, maxWait => 10000, initialSize => 5, removeAbandonedTimeout => 600, removeAbandoned => false, logAbandoned => true, minEvictableIdleTimeMillis => 30001}, connection_name2 => {username => user2, password => pass2, testWhileIdle => true, testOnBorrow => true, testOnReturn => false, timeBetweenEvictionRunsMillis => 30000, maxActive => 20, maxWait => 10000, initialSize => 5, removeAbandonedTimeout => 600, removeAbandoned => false, logAbandoned => true, minEvictableIdleTimeMillis => 30001}}
Notice: Compiled catalog for alexs-macbook-pro.local in environment production in 0.12 seconds
Notice: Applied catalog in 0.02 seconds
Run Code Online (Sandbox Code Playgroud)

感谢 Henrik Lindberg 解释了reduce!

另请参阅此处的 Ruby 文档中给出的解释。

在相关说明中,Henrik 提到 Puppet 5 将包含一个新功能tree_each

可以迭代由数组、哈希和对象容器组成的结构。它可以按深度或广度一阶迭代,并且可以选择控制要包含的内容(容器和/或值和/或包含树的根)。其他操作可以通过链接到过滤器和映射操作的其他迭代函数来执行。

添加此功能的拉取请求在这里