Como avaliar preguiçosamente uma variável arbitrária com Chef
Estou escrevendo uma receita do Chef para instalar o código do aplicativo e executá-lo. A receita precisa ser específica sobre o diretório em que esse código acaba (para executar modelos, configurar o encaminhamento de log, etc.). Assim, o diretório em si aparece em muitos lugares em diferentes receitas.
Eu estou tentando buscar / definir uma variável para que eu possa reutilizá-lo no meu bloco de recursos com interpolação de seqüência de caracteres. Isso é bem direto:
home = node['etc']['passwd'][node['nodejs']['user']]['dir']
Com um exemplo de uso sendo executadonpm install
enquanto dizendo para colocar os downloads do repo no diretório home, assim:
execute "npm install" do
command "npm install #{prefix}#{app} --prefix #{home}"
end
Exceto que o primeiro bloco que define ohome
variável será executada em tempo de compilação. Em um servidor novo, onde minha conta de usuário do nodejs ainda não existe, isso é um problema, dando
NoMethodError undefined method '[]' for nil:NilClass
Eu tenho algumas soluções, mas eu gostaria de uma solução específica para fazer ocasa variável só é buscada no tempo de execução da receita, não no tempo de compilação.
Solução Alternativa 1Avalie dinamicamente a variável home dentro de um bloco de ruby, assim:
ruby_block "fetch home dir" do
block do
home = node['etc']['passwd'][node['nodejs']['user']]['dir']
end
end
Isso não parece realmente funcionar, dando umaNoMethodError undefined home do método para Chef :: Resource :: Directory quando você tenta fazer algo assim:
directory ".npm" do
path "#{home}/.npm"
end
Eu sinto que devo estar fazendo algo errado aqui.
Solução Alternativa 2Preguiçosamente avalie um parâmetro em todos os recursos que precisam dele. Então faça isso:
directory ".npm" do
path lazy "#{node['etc']['passwd'][node['nodejs']['user']]['dir']}/.npm"
end
Mas seria ótimo ter que manter essa linha de código uma vez, armazená-la em uma variável e acabar com ela.
Solução Alternativa 3Crie o usuário em tempo de compilação. Isso obviamente funciona, usando onotificar truque ligado aqui, como isso:
u = user node['nodejs']['user'] do
comment "The #{node['nodejs']['user']} is the user we want all our nodejs apps will run under."
username node['nodejs']['user']
home "/home/#{node['nodejs']['user']}"
end
u.run_action(:create)
Isso resolve exatamente o meu problema, mas há outros casos em que posso imaginar a capacidade de atrasar a avaliação de uma variável, então deixo minha pergunta em suspenso.
O que eu gostariaEu realmente gostaria de poder fazer
home lazy = node['etc']['passwd'][node['nodejs']['user']]['dir']
Mas isso não é sintaxe legal, dandoNameError Não é possível encontrar um recurso para casa no Ubuntu versão 13.10 (que é um erro de sintaxe estranho, mas seja o que for). Existe uma maneira legal de conseguir isso?