如何使用当前食谱模板目录与 chef 一起循环递归复制所有模板

如何使用当前食谱模板目录与 chef 一起循环递归复制所有模板

我试图弄清楚如何构建模板(或文件,因为它以相同的方式工作)文件夹的路径,然后我可以读取它并在循环中使用模板资源,这样每个模板文件都可以在更改时触发通知。

我不能使用 remote_directory 因为我只想在模板改变时通知服务。

我还想避免手动指定模板,因为这些目录中可能有许多文件。此外,它允许我们只更改模板文件夹中的配置,而无需触及配方。

主要问题是这些子目录,如 default、host、host-version 以及 Chef 确定正确模板文件夹时所经过的逻辑。我在想也许 Chef 类中的一个方法我可以从我的自定义食谱中调用,以到达我的逻辑(循环)的起点。

我认为它应该是这样的:

entry_point = CHEF::...getEntryPointDir

entry_point.glob..
.each do

    template fname do
    ...
    end

end

我将不胜感激任何帮助!

答案1

警告:此解决方案使用私有接口,该接口可能会在未经警告的情况下更改或删除。Chef 目前(13.x)不提供解决此问题的支持方法 - 请考虑采用其他方法来解决您的要求。

既然您已经收到警告,下面就是在菜谱中执行的操作:

# Get the Chef::CookbookVersion for the current cookbook
cb = run_context.cookbook_collection[cookbook_name]

# Loop over the array of files.
# 'templates' will also work.
cb.manifest['files'].each do |cookbookfile|
  Chef::Log("found: " + cookbookfile['name'])
end

我分享了一个示例菜谱在上下文中显示这一点。

实际上,这需要更复杂 - 例如,您可能只需要食谱中的部分文件/模板,或者需要以某种方式转换路径。考虑编写一个库函数来列出您感兴趣的文件,并从您的食谱中调用它。

答案2

感谢“zts”。我创建了一个模板目录,其中包含所有 .erb 文件。

cb = run_context.cookbook_collection[cookbook_name]
# you may get 'files' OR 'templates' from manifest
cb.manifest['templates'].each do |tmpl_manifest|
  filepath = tmpl_manifest['path']
  next if not filepath =~ /#{cmk_colo}\/server\/checks\/.*erb/
  filename = tmpl_manifest['name'].split(".erb")[0]
  fileshortpath=filepath.split("/",3)[2]
  template "/opt/omd/sites/prod/etc/check_mk/conf.d/checks/#{filename}" do
    source  fileshortpath
    mode '0644'
    owner 'prod'
    group 'prod'
  end
end

这个函数获取模板目录中所有 .erb 文件的完整/长路径。如果路径与您要循环的目录名称匹配,它会通过标准模板配方创建它。

答案3

感谢@zts 和@Zaur。我本想发布我的完整答案,但最终将两者结合起来。需要注意的是,你的食谱名称必须用引号引起来。这对我来说并不明显,并且对我来说有点阻碍。

第二,我没有使用@Zaur 的 RegEx 搜索来过滤文件路径,而是使用更“ruby-way”的方式进行字符串比较来查看路径是否包含特定目录:

# Get the Chef::CookbookVersion for this cookbook
cb = run_context.cookbook_collection['cookbook_name']

# Loop over the array of files
cb.manifest['files'].each do |cbf|
  # cbf['path'] is relative to the cookbook root, eg
  #   'files/default/foo.txt'
  # cbf['name'] strips the first two directories, eg
  #   'foo.txt'
  filepath = cbf['path']
  filename = cbf['name']

  next if not filepath.include? "directory-to-filter-for/"

  cookbook_file "/etc/service/conf.d/#{filename}" do
    source "directory-to-filter-for/#{filename}"
    mode 0600
    owner "root"
    group "root"
  end
end

我将其用于文件,但您也可以使用模板。只需将第 14 行的“文件”块替换为“模板”块即可。然后将第 5 行更改为使用模板而不是文件:

cb.manifest['templates'].each do |cbf|

答案4

在 Chef > 12.19 中,对清单进行了重大更改 (RFC 67),它将所有文件合并到以下食谱中::all_files

https://chef.github.io/chef-rfc/rfc067-cookbook-segment-deprecation.html

要返回所有模板的列表,您现在使用:

run_context.cookbook_collection[:examplecookbook].files_for('templates')

相关内容