2012-11-08 11 views
5

Ho esteso la classe di ricette tramite un modulo per fornire alcune proprietà che mi danno accesso globale ai miei percorsi, che sono costruiti dinamicamente. Esempio:ricetta chef - metodi di modulo non disponibili all'interno delle risorse

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

class Chef::Recipe 
    include Variables 
end 

Il problema è, che entro i blocchi di risorse questi metodi non sono disponibili.

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

NoMethodError: metodo non definito `user_home' per Chef :: risorse :: Bash

Il comportamento strano è, che la proprietà utente funziona bene, ma l'una proprietà utilizzata all'interno del blocco di codice non funziona .

Dopo questo ho inserito anche il modulo in tutte le risorse in questo modo:

class Chef::Resource 
    include Variables 
end 

Ora la mia proprietà user_home si comporta in modo diverso all'interno di blocchi di risorse rispetto a quando utilizzato "al di fuori", che significa:

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

crea/home/user_name/new_dir

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

risultati in/home // nuovo_ dir

Ho provato questo con un piccolo script di test e tutto funziona correttamente.

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 

Quindi per me sembra che questo deve essere un problema specifico di Chef.

Qualcuno può spiegarmi perché questo sta accadendo?

Esiste una soluzione migliore per un accesso globale ai miei percorsi e attributi che vengono generati dinamicamente?

Grazie.

risposta

1

Puoi inserire i tuoi percorsi come attributi?

O a livello ambientale o a livello di nodo?

Facciamo qualcosa di simile con gli attributi cookbook se lo facciamo per costruire le istruzioni di installazione. In questo caso costruiamo le istruzioni di installazione da un databag

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" 

Con tutto ciò che ha detto penso l'estensione della classe risorse dovrebbe avete visto bene. Quando dici che ti sei comportato in modo diverso all'interno delle risorse piuttosto che all'esterno. Directory è una risorsa e quindi in questo caso si sta comportando in modo diverso tra le due risorse

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

Quindi, forse si tratta di un problema con una delle risorse che sta causando il comportamento incoerente?

+0

il problema con gli attributi è che essi non considerano i valori ignorati nel ruolo o l'ambiente:
default [ 'user'] = 'nome_utente' default [ 'user_home'] = "/ home # {nodo [ 'user ']} " ecco perché ho creato il mio percorso user_home nella ricetta (o dove ne ho bisogno) – DELUXEnized

+0

il comportamento incoerente è causato perché per qualche motivo, alcune proprietà sono valutate all'interno del contesto del blocco (come l'attributo del codice su bash) e altri (come utente e gruppo) sono valutati all'interno del contesto della ricetta, dove ho definito le proprietà. Ad ogni modo, non dovrei includere lo stesso modulo all'interno della classe Resource, perché nel suo contesto il nodo non è disponibile e restituisce valori diversi. – DELUXEnized

+0

Si può usare una ricetta per impostare l'attributo a livello di nodo nodo ['user_home'] = "/ home # {nodo ['utente']}" e quindi si sta giocando nel modello di precedenza disposto da opscode. Questa ricetta potrebbe essere aggiunta all'inizio del ruolo? Il significato di tutte le ricette potrebbe quindi sfruttare quell'attributo e trasferirlo in risorse? Forse è un po 'strano per quello che stai cercando di fare Oppure utilizzare le variabili di ambiente? – PatrickWalker

0

ho avuto metodi di successo iniettando nel l'ambito di una risorsa come segue:

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 

La chiave qui è Chef::Resource.send(:include, ...) che inietta il modulo direttamente nella classe Chef::Resource, rendendo i metodi del modulo disponibili per tutte le risorse.

Problemi correlati