简体   繁体   English

Puppet - 在迭代哈希时,如果hiera中不存在,则设置清单中的默认值

[英]Puppet - set defaults in manifest if not present in hiera when iterating over hash

I am iterating over many entries in a hiera hash, and wish to remove identical duplicate lines from hiera by setting defaults in the manifest (such as ensure , groups , managehome etc), and have the defaults overridden IF the duplicate key/value pair exists in hiera. 我正在迭代hiera散列中的许多条目,并希望通过设置清单中的默认值(例如ensuregroupsmanagehome等)从hiera中删除相同的重复行,并且如果存在重复的键/值对,则覆盖默认值在hiera。

To date, everything I have tried fails to get the default values. 到目前为止,我尝试过的所有内容都无法获得默认值。 I get the idea that I need to declare a resource, but am uncertain. 我认为我需要声明一个资源,但我不确定。

I have tried setting "default_values_hash" in the lookup and other methods, but nothing appears to pass defaults into the iteration and --debug output 我已尝试在查找和其他方法中设置“default_values_hash”,但似乎没有任何内容将默认值传递给迭代和--debug输出

This is a (pseudo) example of my manifest and hiera data. 这是我的清单和层次数据的(伪)示例。 Any guidance is sincerely appreciated. 任何指导都真诚地感谢。 Thank you. 谢谢。

class test (
  Hash $testhash = lookup('test::hash', "merge" => 'hash'}),
){

  $testhash.each |$key, $value| {
    user { $key :
      ensure     => $value['ensure'],
      name       => $value['name'],
      password   => $value['password'],
      groups     => $value['groups'],
      managehome => $value['managehome'],
    }
  }
}
include class test

in Hiera: 在Hiera:

test::hash:

'fred':
  name:         fred
  password:     somepassword
  groups:       wheel
  managehome:   true

'mary':
  name:         mary
  password:     otherpassword

'john':
  name:         john
  password:     anotherpassword

'harry':

Setting resource defaults in the manifest (with capitalized User ) does not pass into the iteration, though it does if I keep all data in the manifest (too much data to do that). 在清单中设置资源默认值(使用大写的User )不会传递到迭代中,但如果我将所有数据保留在清单中(太多数据要做)。

The lookup function gives you the ability to establish a default value for the hash itself, but not really for the keys and values inside the hash. lookup函数使您能够为散列本身建立默认值,但不能真正为散列内的键和值建立。 Additionally, using the lookup function as a class parameter value in Puppet will be superseded by automatic parameter bindings. 此外,使用lookup函数作为Puppet中的类参数值将被自动参数绑定取代。 In other words, your lookup function in this context does nothing because Puppet is preferring automatic parameter bindings over it, and you are using those (this is definitely true for lookup in conjunction with Hiera 5, which it appears you are using). 换句话说,你在这个上下文中的lookup函数什么都不做,因为Puppet更喜欢对它进行自动参数绑定,而你正在使用它们(对于Hiera 5的lookup ,这肯定是正确的,你看起来正在使用它)。 I personally find this behavior annoying, but it is what it is. 我个人觉得这种行为很烦人,但事实就是如此。 Edit: Never mind on that specific reasoning; 编辑:没关系那个具体的推理; the parameter is called $testhash and not $hash . 该参数称为$testhash而不是$hash If that parameter is coming from module data though, then the lookup will still be ignored since Puppet only allows automatic parameter binding for module data. 如果该参数来自模块数据,那么lookup仍将被忽略,因为Puppet仅允许模块数据的自动参数绑定。

I am surprised that the resource defaults are not working here for you. 我很惊讶资源默认设置不适合你。 I have to believe that this is either unintended, or something was implemented wrong regarding them when you went that route. 我不得不相信这是无意的,或者当你走这条路线时,某些事情被误解了。

Regardless, here is a guaranteed method for you. 无论如何,这是一个有保障的方法。 First, we implement per-expression default attributes: https://puppet.com/docs/puppet/5.3/lang_resources_advanced.html#per-expression-default-attributes 首先,我们实现每个表达式的默认属性: https//puppet.com/docs/puppet/5.3/lang_resources_advanced.html#per-expression-default-attributes

class test (
  Hash $testhash = lookup('test::hash', "merge" => 'hash'}),
){

  $testhash.each |String $key, Hash $value| {
    user { 
      default:
        ensure     => present,
        name       => 'username',
        password   => 'userpassword',
        groups     => ['usergroups'],
        managehome => false,
      ;
      $key:
        ensure     => $value['ensure'],
        name       => $value['name'],
        password   => $value['password'],
        groups     => $value['groups'],
        managehome => $value['managehome'],
      ;
    }
  }
}

One problem still remains here though, which is that you are establishing values for the attributes in the second block for all iterations. 但是仍然存在一个问题,即您要为所有迭代在第二个块中建立属性值。 If those key-value pairs are undefined, Puppet will error instead of defaulting to another value. 如果这些键值对未定义,Puppet将错误而不是默认为另一个值。 We need to instruct Puppet to only establish values for attributes if you have defined a value for them in the first place. 如果您首先为它们定义了值,我们需要指示Puppet仅为属性建立值。 Thankfully, we can do this with the * attribute: https://puppet.com/docs/puppet/5.3/lang_resources_advanced.html#setting-attributes-from-a-hash 值得庆幸的是,我们可以使用*属性执行此操作: https//puppet.com/docs/puppet/5.3/lang_resources_advanced.html#setting-attributes-from-a-hash

class test (
  Hash $testhash = lookup('test::hash', "merge" => 'hash'}),
){

  $testhash.each |String $key, Hash $value| {
    user { 
      default:
        ensure     => present,
        name       => 'username',
        password   => 'userpassword',
        groups     => ['usergroups'],
        managehome => false,
      ;
      $key:
        * => $value,
      ;
    }
  }
}

One recommendation here would be to make your lambda iterator variables $key, $value a bit more transparently named. 这里的一个建议是使你的lambda迭代器变量$key, $value更透明地命名。 Another note is the caveat that for the * attribute to work, your hash keys must match Puppet attribute names. 另一个注意事项是,要使*属性起作用,您的哈希键必须与Puppet属性名称匹配。

Updated question: In the situation where the hash has a key with a nil value, you can set an empty hash as the default value for the key's value in the lambda iterator parameters. 更新的问题:在散列具有nil值的键的情况下,您可以将空散列设置为lambda迭代器参数中键值的默认值。 The empty hash will replace the undef (Puppet nil ) for the $value during that iteration. 空哈希将在该迭代期间替换$valueundef (Puppet nil )。 This will ensure that no attributes and values are included in the * operator and that all the defaults will prevail. 这将确保*运算符中不包含任何属性和值,并且所有默认值都将占优势。

class test (
  Hash $testhash = lookup('test::hash', "merge" => 'hash'}),
){

  $testhash.each |String $key, Hash $value = {}| {
    user { 
      default:
        ensure     => present,
        name       => 'username',
        password   => 'userpassword',
        groups     => ['usergroups'],
        managehome => false,
      ;
      $key:
        * => $value,
      ;
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM