Puppet报错:重复调用host_present时ensure参数已定义无法重定义
host_present资源重复声明的参数冲突问题 嘿,这个问题我熟!咱们先拆解一下你遇到的错误根源,再一步步解决。
错误原因
你看到的错误Parameter 'ensure' is already set on host_present[test],本质是Puppet的资源唯一性规则在起作用:Puppet要求每个资源实例(这里就是host_present["test"])在整个目录编译过程中只能被声明一次,不能重复定义并修改参数。你两次调用了同一个标题test的host_present,第一次设ensure => present,第二次又设ensure => absent,这就违反了唯一性原则,Puppet自然会报错。
另外还要提一句:你的host_present定义里固定写了host { 'puppet_host': ... },就算你给host_present用不同标题,多个实例也会创建同名的host资源,同样会引发冲突,这个咱们后面一起解决。
解决方案
根据你的需求,分两种情况处理:
情况1:需要根据条件切换ensure状态
如果你的目标是在不同场景下(比如不同节点、不同环境)让host_present[test]呈现不同的ensure状态,不要重复声明同一个实例,而是用条件判断来动态设置参数值:
# 示例:根据节点名称决定状态 $ensure_state = $facts['fqdn'] == 'devopenstack' ? { true => 'absent', default => 'present', } # 只声明一次host_present实例 host_present{"test": ensure => $ensure_state}
你也可以通过Hiera来管理这个状态值,更灵活:
# 从Hiera获取ensure状态 $ensure_state = lookup('host_present_test_ensure', String, 'first', 'present') host_present{"test": ensure => $ensure_state}
情况2:确实需要两个独立的host_present实例
如果你是想创建两个不同的资源实例(比如管理两个不同的host条目),那必须给它们不同的标题,同时还要修改host_present定义,让里面的host资源名称唯一,避免新的冲突:
# 修改define,用$title作为host资源名称的一部分,保证唯一性 define host_present($ensure = present) { host { "puppet_host_${title}": persona => 'TEST', url => 'https://user:password', ensure => $ensure, } } # 用不同标题声明两个独立实例 host_present{"test-present": ensure => present} host_present{"test-absent": ensure => absent}
这样每个host_present实例对应的host资源名称分别是puppet_host_test-present和puppet_host_test-absent,就不会重复了。
内容的提问来源于stack exchange,提问作者Sathish

