6

我对 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

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

这可能吗?如果是这样,我做错了什么?如果没有,我的选择是什么。

谢谢

编辑

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

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
4

1 回答 1

2

你可以template_dir在你的内部ruby_block而不是在顶层定义——这样就可以了。

find是 Ruby 标准库的一部分,将递归遍历一个目录。使用它会导致一些更清洁的东西:

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

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

另外,我对您拥有的“服务器”字符串有些困惑——我不确定在什么环境下会解析到您的templates目录。无论如何,如果您想访问食谱中所有模板的列表,这里有一个可用的数组:run_context.cookbook_collection[cookbook_name].template_filenames

于 2013-10-06T20:44:33.983 回答