2013-04-04 45 views
6

Tôi rất mới với Đầu bếp và đang cố gắng tìm ra khuôn mẫu (có vẻ rất tuyệt). Trong cấu trúc triển khai cũ của tôi, tôi có một thư mục mà tôi chỉ muốn sao chép. Nó có một số tham số cấu hình nằm rải rác khắp các tệp trong thư mục. Tôi đã đi trước và cố gắng để trừu tượng các tham số đi vào một tập tin thuộc tính (sạch hơn nhiều), nhưng đang gặp khó khăn khi cài đặt nó với Chef. Tôi đã sửa đổi các phần mở rộng của tất cả các tập tin với ERB trong chúng để kết thúc với .erb (Tôi đến từ một nền Rails, vì vậy điều này có vẻ tự nhiên với tôi). Ví dụ, tôi đã có một tập tin có tên là run.conf, và nó bây giờ được đặt tên là run.conf.erb.Mẫu đầu bếp có các thư mục đệ quy

Lý tưởng nhất là tôi muốn có một khối mẫu trong công thức chỉ sao chép tất cả các tệp trong thư mục và cập nhật các tệp .erb đó (loại bỏ phần mở rộng .erb) với các biến tôi cung cấp. Dưới đây là ví dụ về nơi tôi đang ở cho đến thời điểm này:

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 

Tôi đã đặt một thư mục có tên là máy chủ trong mẫu/mặc định và thư mục đó chứa các tệp tôi muốn tạo mẫu. Biến # {node ["dcm4chee"] ["home"]} là vị trí của nơi tôi muốn đặt các tập tin trên máy đích. Lý tưởng nhất là tôi muốn làm điều này mà không đặt tên các tệp cụ thể trong công thức vì cách đó tôi không phải chạm vào công thức nếu tôi sửa đổi nội dung của thư mục máy chủ để triển khai.

Điều này có khả thi không? Nếu vậy tôi đang làm gì sai? Nếu không, lựa chọn thay thế của tôi là gì.

Cảm ơn

EDIT

Sau khi suy nghĩ về vấn đề này một chút, tôi đã cố gắng sử dụng một số mã tùy chỉnh ruby ​​để làm điều này. Đây là nỗ lực hiện tại của tôi mà là thất bại với một NoMethodError đề cập đến tempate_dir từ cuộc gọi ban đầu trong ruby_block.

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 
+0

Làm tất cả các tệp của bạn cần có thông số hay chỉ một vài? – cmur2

+0

Chỉ cần một vài cho bây giờ, nhưng lý tưởng tôi muốn giữ chúng lại với nhau (những người cần templating, và những người không cần) vì vậy nó siêu dễ dàng để thêm/loại bỏ các tập tin trong tương lai. – Jon

+0

Bạn có thể sử dụng ruby ​​để lấy tất cả các tệp trong thư mục mẫu, liên quan đến công thức. Sau đó, bạn chỉ cần sử dụng tài nguyên 'template' bên trong một khối' files.each'. – cassianoleal

Trả lời

2

Bạn có thể xác định template_dir bên trong ruby_block của bạn thay vì ở level- hàng đầu mà sẽ chỉ làm việc tốt.

find là một phần của thư viện chuẩn của Ruby và sẽ đệ quy đi qua thư mục. Sử dụng nó sẽ dẫn đến một cái gì đó hơi bụi:

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 

Nói chung, nếu bạn đang viết bất kỳ loại của logic nhẹ phức tạp, bạn nên cân nhắc viết một LWRP thay vì đưa nó vào công thức của bạn. Việc biên dịch/thực thi hai pha gây ra rất nhiều hành vi không trực quan (như thực tế là khối không thể tra cứu template_dir), và bởi vì viết LWRP cho phép bạn xác thực đầu vào, viết kiểm thử và thực hiện công việc tốt hơn để đảm bảo tính không hợp lệ .

Ngoài ra, tôi hơi bối rối về chuỗi 'máy chủ' mà bạn có - Tôi không chắc chắn về môi trường nào sẽ giải quyết cho thư mục templates của bạn. Trong mọi trường hợp, nếu bạn muốn truy cập vào danh sách tất cả các mẫu trong sách dạy nấu ăn của bạn, có một mảng sẵn có tại đây: run_context.cookbook_collection[cookbook_name].template_filenames

Các vấn đề liên quan