带有递归目录的厨师模板

时间:2013-04-04 20:33:07

标签: chef

我是Chef的新手,我正在试图找出模板(这看起来很酷)。在我的旧部署结构中,我有一个我只想复制的目录。它有许多配置参数分散在目录中的整个文件中。我已经开始尝试将这些参数抽象为一个属性文件(更干净),但是在使用Chef安装它时遇到了麻烦。我用ERB修改了所有文件的扩展名以.erb结尾(我来自Rails背景,所以这对我来说似乎很自然)。例如,我有一个名为run.conf的文件,它现在名为run.conf.erb。

理想情况下,我希望在配方中有一个模板块,它只复制目录中的所有文件,并使用我提供的变量更新这些.erb文件(删除.erb扩展名)。这是我到目前为止的一个例子:

template "#{node["dcm4chee"]["home"]}" do
  source "server/"
  variables(
    "java_mem_opts" => node["dcm4chee"]["java_mem_opts"],
    "db_username" => node["dcm4chee"]["admin"]["username"],
    "db_password" => node["dcm4chee"]["admin"]["password"],
    "db_hostname" => node["mysql"]["hostname"],
    "db_port" => node["mysql"]["port"]
)
end

我在templates / default下放了一个名为server的文件夹,该文件夹包含我想模板化的文件。 #{node [“dcm4chee”] [“home”]}变量是我想将文件放在目标机器上的位置。理想情况下,我想在没有命名配方中的特定文件的情况下执行此操作,因为这样,如果我修改服务器目录的内容以进行部署,我就不必触摸配方。

这可能吗?如果是这样,我做错了什么?如果没有,我的替代方案是什么。

由于

修改

在考虑了这一点后,我尝试使用一些自定义ruby代码来执行此操作。这是我当前尝试失败的NoMethodError引用ruby_block中初始调用的tempate_dir。

def template_dir(file)
  Dir.foreach("server") do |file|
    if File.file?(file)
      template "#{node["dcm4chee"]["home"]}/#{file}" do
        source "server/#{file}"
          variables(
            "java_mem_opts" => node["dcm4chee"]["java_mem_opts"],
            "db_username" => node["dcm4chee"]["admin"]["username"],
            "db_password" => node["dcm4chee"]["admin"]["password"],
            "db_hostname" => node["mysql"]["hostname"],
           "db_port" => node["mysql"]["port"]
          )
      end
    else
      directory "#{node["dcm4chee"]["home"]}/#{file}" do
        action :create
      end
      template_dir(file)
    end
  end
end

ruby_block "template the whole server directory" do
  block do
    template_dir("server")
  end
end

1 个答案:

答案 0 :(得分:2)

您可以在template_dir内定义ruby_block,而不是在最高级别定义find

ruby_block "recursive templating" do block do require 'find' root = 'server' Find.find(root) do |file| if File.file?(file) template "#{node["dcm4chee"]["home"]}/#{file}" do source file variables( "java_mem_opts" => node["dcm4chee"]["java_mem_opts"], "db_username" => node["dcm4chee"]["admin"]["username"], "db_password" => node["dcm4chee"]["admin"]["password"], "db_hostname" => node["mysql"]["hostname"], "db_port" => node["mysql"]["port"] ) end end end end end 是Ruby标准库的一部分,将以递归方式遍历目录。使用它会产生一些稍微清洁的东西:

template_dir

一般来说,如果您正在编写任何类似的复杂逻辑,您应该考虑编写LWRP而不是将其放入您的配方中。两阶段编译/执行事情会导致许多不直观的行为(比如块不能查找templates),并且因为编写LWRP可以验证输入,编写测试,并且执行更好地确保幂等性。

另外,我对服务器'有点困惑。你有的字符串 - 我不确定将在什么环境中解析你的run_context.cookbook_collection[cookbook_name].template_filenames目录。在任何情况下,如果您想要访问食谱中所有模板的列表,可以在此处找到一个数组:{{1}}