鉴于数据结构
$local_users => {
"user" => {
"ssh" => {
"config_entries" => [
{ "host" => "dummyhost",
"lines" => [
"ProxyCommand /usr/bin/corkscrew proxy.example.net 8080 %h %p"
]
}
]
}
}
}
我已经整理了几个reduce调用,但不确定是否有更有效的方法来确定是否存在匹配某些条件的元素。如果发现匹配,我认为这至少会开始跳过后续项目,但是看起来有点笨拙做3次减少调用以提取嵌套这一点的内容并且想知道是否有更好的模式在puppet中提取数据以确定是否有什么东西是否需要。
$require_corkscrew = $local_users.reduce(false) |$memo, $user| {
$memo or dig44($user[1], ['ssh', 'config_entries'], []).reduce |$memo, $entry| {
$memo or $entry['lines'].reduce |$memo, $line| {
$memo or $line.match(/ProxyCommand.*corkscrew/)
}
}
}
if $require_corkscrew {
$corkscrew_ensure = 'present'
} else {
$corkscrew_ensure = 'absent'
}
package {'corkscrew':
ensure => $corkscrew_ensure,
}
想知道在木偶中是否有更好的模式来提取数据以确定是否需要某些东西。
围绕数据结构的方式有一些可能的改进:
至于计算模式,
any()
函数,因为这可以实现真正的短路。keys()
和values()
函数,因为它们至少可以在处理复杂数据结构时降低代码的认知负荷。match()
在数组上以有用的方式工作。这是一种我比原始代码更好的方法。它使用嵌套的any()
计算和match
函数的数组版本,而不是嵌套的缩减。它依赖于undef
是假的,并使用dig()
和then()
来处理可选的哈希键。总的来说,我认为它更清晰,重量更轻一些,但是你可以做很多事情来实现分析复杂数据的简单代码。
$require_corkscrew = $local_users.values.any |$user| {
$user.dig('ssh', 'config_entries').then |$entries| {
$entries.any |$entry| {
$entry.dig('lines').then |$lines| {
! empty($lines.match(/ProxyCommand.*corkscrew/))
}
}
}
}
有可能用围绕标量match()
的另一个any()
替换阵列式match()
,但是虽然它有可能在元素方面稍早地短路,但必须权衡(可能)效率减少函数调用的数量,以及在函数内部而不是在DSL级别进行迭代的改进。