Comment évaluer paresseusement une variable arbitraire avec Chef

Je suis en train d'écrire une recette Chef d'installer notre code de l'application et de l'exécuter. La recette doit être particulier à propos de l'annuaire, ce code se termine (pour l'exécution de modèles, le réglage de journal de transfert, etc.). Ainsi, le répertoire lui-même apparaît dans beaucoup d'endroits dans différentes recettes.

Je suis en train de chercher/définition d'une variable afin que je puisse le réutiliser dans mon ressource bloc avec une chaîne d'interpolation. C'est assez simple:

home = node['etc']['passwd'][node['nodejs']['user']]['dir']

Avec un exemple d'utilisation en cours d'exécution npm install tout raconter à gratter les pensions de téléchargements dans le répertoire d'accueil, comme ceci:

execute "npm install" do
  command "npm install #{prefix}#{app} --prefix #{home}"
end

Sauf que le premier bloc qui définit la home variable sera exécuté au moment de la compilation. Sur un nouveau serveur, d'où ma nodejs compte d'utilisateur peut ne pas exister encore, c'est un problème, en donnant un

NoMethodError undefined method '[]' for nil:NilClass

J'ai quelques solutions de contournement, mais je voudrais une solution spécifique pour faire de la maison variable uniquement être récupérée à la recette de l'exécution, pas le temps de compilation.


Solution de contournement 1

D'évaluer de façon dynamique la maison de la variable à l'intérieur d'un rubis bloc, comme suit:

ruby_block "fetch home dir" do
  block do
    home = node['etc']['passwd'][node['nodejs']['user']]['dir']
  end
end

Cela ne semble pas réellement de travail, donnant un NoMethodError méthode non à la maison pour le Chef:::: Répertoire lorsque vous essayez de faire quelque chose comme ceci:

directory ".npm" do
  path "#{home}/.npm"
end

Je sens que je dois faire quelque chose de mal ici.

Solution 2

Paresseusement évaluer un paramètre sur chaque ressource. Donc au lieu de faire ceci:

directory ".npm" do
  path lazy "#{node['etc']['passwd'][node['nodejs']['user']]['dir']}/.npm"
end

Mais ce serait vraiment génial d'avoir juste à maintenir cette ligne de code à la fois, les stocker dans une variable et faire avec elle.

Solution 3

Créer l'utilisateur au moment de la compilation. Bien sûr, cela fonctionne, en utilisant la informer truc lié icicomme ceci:

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)

Cela résout mon problème exactement, mais il y a d'autres cas où, je peux imaginer vouloir la capacité à retarder l'évaluation d'une variable, je laisse donc ma question stand.

Ce que je voudrais

Je voudrais vraiment être en mesure de faire

home lazy = node['etc']['passwd'][node['nodejs']['user']]['dir']

Mais ce n'est pas légal de la syntaxe, de donner NameError Ne peut pas trouver une ressource pour la maison sur la version ubuntu 13.10 (ce qui est une étrange erreur de syntaxe, mais soit). Est-il un moyen légal pour accomplir cette?

source d'informationauteur Patrick M