Puppet Agent拉取catalog时报nginx配置File资源重复声明
问题根因
报错本质是Puppet编译catalog时,检测到/etc/nginx/nginx.conf这个目标路径被两个独立的File资源重复声明:一个来自你自定义的icarrierdata_nginx::files类,另一个来自你无法修改源码的第三方nginx模块。
之前两次尝试无效的原因:
force属性和重复声明检测逻辑完全无关:force仅用于控制Puppet删除非空文件/目录时的行为,不参与资源唯一性校验,添加后不会影响报错结果。if ! defined(File['/etc/nginx/nginx.conf'])判断失效:defined()是动态检测逻辑,结果强依赖代码的评估顺序。如果你的自定义类先被评估,判断会返回true,你的File资源会被优先注册,等第三方nginx模块后续评估到自身的同路径File资源时,因为模块内部没有做重复判断,就会直接抛出重复声明错误。
解决方案
因为第三方模块源码无法修改,优先用不需要改动第三方代码的方式解决:
方案1(推荐,无加载顺序依赖)
放弃自定义类里单独新建File资源的逻辑,改用Puppet的资源收集器,直接对catalog里已存在的/etc/nginx/nginx.conf资源做属性覆盖,不新建资源,从根源上避免重复声明。
修改你的icarrierdata_nginx/manifests/files.pp代码:
class icarrierdata_nginx::files inherits icarrierdata_nginx::params { $source_base = "puppet:///modules/${module_name}" # 收集已声明的同路径File资源,直接覆盖需要的属性 File<| path == '/etc/nginx/nginx.conf' |> { content => template("${module_name}/nginx.conf.erb"), owner => 'root', group => 'root', notify => Service['nginx'], } }
这种方式不受类加载顺序影响,不管第三方模块的资源先注册还是后注册,收集器都会命中对应资源,把你需要的配置属性覆盖上去。
方案2(有加载顺序要求)
如果资源收集器因为环境版本限制无法使用,就强制调整类的评估顺序,让第三方nginx模块先被加载,再加载你的自定义类。这样你原来的if ! defined()判断就能检测到第三方模块已经声明的资源,不会再重复创建自己的File资源。
具体实现时,在你的节点/角色定义文件里,通过contain强制指定加载顺序:
# 先加载第三方nginx模块,再加载自定义类 contain 'nginx' contain 'icarrierdata_nginx::files'
内容的提问来源于stack exchange,提问作者Nicholas Maestrello Agiz
相关产品推荐
相关产品推荐

