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 1

Avalie 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 2

Preguiç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 3

Crie 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 gostaria

Eu 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?

questionAnswers(3)

yourAnswerToTheQuestion