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
Vous devez vous connecter pour publier un commentaire.
Je n'ai pas testé ce code, mais j'ai fait quelque chose de similaire dans les livres de cuisine et utilisé un lambda de retarder l'évaluation comme suit:
Pour
ruby_block
toutes les variables dans le bloc devra être mondial, comme quelque chose de défini au sein du bloc local.Vous ne pouvez pas utiliser une lambda pour retard d'exécution dans une bibliothèque, donc
ruby_block
fonctionne bien dans ce cas.@thoughtcroft réponse ne fonctionne pas pour moi, au chef-client 12.8.1
Dans ce cas, j'ai besoin de code dans des ressources et de l'appeler avec un paresseux attributs.
Pas de solution élégante, mais cela fonctionne pour moi.