2012-11-08 25 views
5

Tôi đã mở rộng lớp công thức thông qua một mô-đun để cung cấp một số thuộc tính cho phép tôi truy cập toàn cầu vào đường dẫn của mình. Ví dụ:công thức đầu bếp - phương pháp mô-đun không có sẵn trong tài nguyên

module Variables 
    def user 
    "user_name" 
    end 
    def user_home 
    "/home/#{node['user']}" 
    end 
end 

class Chef::Recipe 
    include Variables 
end 

Vấn đề là, trong tài nguyên chặn các phương pháp này không có sẵn.

bash "do_something_with_property" do 
    user user 
    code "somecommand #{user_home}" 
end 

NoMethodError: Phương pháp xác định 'user_home' cho Chef :: Resource :: Bash

Các hành vi kỳ lạ là, rằng các tài sản sử dụng hoạt động tốt, nhưng một tài sản sử dụng trong khối mã không hoạt động .

Sau này tôi cũng bao gồm các module vào tất cả các tài nguyên bằng cách làm này:

class Chef::Resource 
    include Variables 
end 

Bây giờ sở hữu user_home tôi cư xử khác nhau trong khối tài nguyên hơn so với khi sử dụng "bên ngoài", có nghĩa là:

directory "#{user_home}/new_dir" do 
    action :create 
end 

tạo/home/user_name/new_dir

bash "create_dir" do 
    code "mkdir #{user_home}/new_dir" 
end 

kết quả trong/home // new_ dir

Tôi đã thử nghiệm điều này bằng một tập lệnh thử nghiệm nhỏ và mọi thứ đều hoạt động tốt.

module MyModule 
def module_method 
    puts "blablalba" 
end 
end 

class A 
def block_method (&block) 
    block.call 
end 
end 

class B 
include MyModule 

def doit 
    a = A.new 
    a.block_method { module_method } 
end 
end 

B.new.doit 

Vì vậy, với tôi, có vẻ như đây phải là vấn đề cụ thể của Đầu bếp.

Bất cứ ai có thể giải thích cho tôi, tại sao điều này xảy ra?

Có giải pháp nào tốt hơn cho việc truy cập toàn cầu vào đường dẫn và thuộc tính của tôi được xây dựng động không?

Cảm ơn.

Trả lời

1

Bạn có thể đặt đường dẫn của mình dưới dạng thuộc tính không?

Hoặc ở cấp độ môi trường hoặc cấp độ nút?

Chúng tôi làm điều gì đó tương tự với các thuộc tính sách dạy nấu ăn là chúng tôi làm điều này để xây dựng các hướng dẫn cài đặt. Trong trường hợp này, chúng tôi xây dựng hướng dẫn cài đặt từ một thẻ dữ liệu

default['splunk']['server'] = Chef::DataBagItem.load('Splunk', 'Install')["Server"] 
default['splunk']['install_args'] = Chef::DataBagItem.load('Splunk', 'Install')["Arguments"] 

default['splunk']['installcommands'] = "RECEIVING_INDEXER=\"#{default['splunk']['server']}\" #{default['splunk']['install_args']} /quiet" 

Với tất cả những gì đã nói, tôi cho rằng phần mở rộng của lớp tài nguyên sẽ thấy bạn ổn. Khi bạn nói hành vi khác nhau bên trong tài nguyên như trái ngược với bên ngoài. Directory là một nguồn tài nguyên cũng như vậy trong trường hợp đó nó hành xử khác nhau giữa hai nguồn

http://wiki.opscode.com/display/chef/Resources#Resources-Directory

Vì vậy, có lẽ đó là một vấn đề với một trong những nguồn lực mà gây ra các hành vi không phù hợp?

+0

vấn đề với các thuộc tính là họ không xem xét giá trị ghi đè trong vai trò hoặc môi trường:
mặc định [ 'user'] = 'user_name' mặc định [ 'user_home'] = "/ home # {nút [ 'người sử dụng ']} " đó là lý do tại sao tôi xây dựng đường dẫn user_home trong công thức (hoặc bất cứ nơi nào tôi cần) – DELUXEnized

+0

hành vi không nhất quán gây ra vì một số lý do, một số thuộc tính được đánh giá trong ngữ cảnh khối (như thuộc tính mã trên bash) và những người khác (như người dùng và nhóm) được đánh giá trong ngữ cảnh công thức, nơi tôi đã xác định các thuộc tính. Dù sao, tôi không nên bao gồm cùng một mô-đun trong lớp Tài nguyên, bởi vì trong ngữ cảnh của nó, nút không có sẵn và trả về các giá trị khác nhau. – DELUXEnized

+0

Bạn có thể sử dụng công thức để đặt thuộc tính ở cấp độ nút nút ['user_home'] = "/ home # {node ['user']}" và sau đó nó sẽ được chơi vào mô hình ưu tiên được đặt ra bởi opscode. Công thức đó có thể được thêm vào phần đầu của vai trò? Có nghĩa là tất cả các công thức nấu ăn sau đó có thể tận dụng thuộc tính đó và nó có thể được chuyển vào tài nguyên? Có thể đó là một chút sôi nổi cho những gì bạn đang tìm kiếm để làm Hoặc sử dụng các biến môi trường? – PatrickWalker

0

tôi đã có phương pháp thành công tiêm vào phạm vi của một tài nguyên như sau:

libraries/helper.rb:

module MyCookbook 
    module Helper 
    def my_method 
     "foobar" 
    end 
    end 
end 

Chef::Resource.send(:include, MyCookbook::Helper) 

recipes/default.rb:

file 'foo' do 
    content my_method 
end 

Mấu chốt ở đây là Chef::Resource.send(:include, ...) mà tiêm module của bạn trực tiếp vào lớp Chef::Resource, làm cho các phương thức mô-đun của bạn có sẵn cho tất cả các tài nguyên của bạn.

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