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

Append a hash to a series of nested hashes in Puppet4

给出的是 hieradata 中哈希的哈希:

profile::jdbc::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',
}

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

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

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

  $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)

然后检查一下:

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

但是,您提到您的数据来自 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)
}

注意,由于Puppet中可以添加Hashes,因此可以避免使用stdlib中的merge函数:

  $merged = $connections.map |$k,$v| {
    {$k => $jdbc_default + $v}
  }

(注意 {'a' => 1} + {'b' => 2} returns {'a' => 1, 'b' => 2}。如果两个键都在,则右侧获胜,即 {'a' => 1, 'b' => 2} + {'a' => 2} returns {'a' => 2, 'b' => 2}.)

现在,如果您需要哈希的哈希,而不是哈希数组,您可以通过 reduce 函数实现:

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

或:

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

这是如何工作的:

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

感谢 Henrik Lindberg 解释 reduce!

的用法

另请参阅 Ruby 文档中给出的解释 here

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

that can iterate over a structure consisting of Array, Hash and Object containers. It can iterate in depth or breadth first order and there are options for controling what to include (containers and/or values and/or include the root of the tree). Other operations can be performed by chaining to other iterative functions for filter and map operations.

添加此功能的拉取请求是 here