web-dev-qa-db-fra.com

Comment vérifier si un dossier existe dans Chef?

Voici mon code:

if !::File.exist?("#{node['iis']['home']}\\backup\\BkpB4Chef")
 windows_batch "Backup IIS Config" do
  code <<-EOH
   "#{node['iis']['home']}"\\appcmd add backup BkpB4Chef
  EOH
 end
end

Il indique toujours que le fichier existe et exécute la boucle.

12
Sony Koithara

Vous devez utiliser chefs de garde ici. Les gardes spécifient l'exécution conditionnelle, mais insèrent toujours la ressource dans la collection de ressources. Dans votre exemple et votre réponse jtblin, la ressource n'est jamais ajoutée à la collection (que j'expliquerai un peu plus loin dans un instant).

Voici un code de travail pour vous aider à démarrer:

windows_batch "Backup IIS Config" do
  code %Q|#{node['iis']['home']}"\\appcmd add backup BkpB4Chef|
  not_if { ::File.directory?("#{node['iis']['home']}\\backup\\BkpB4Chef") }
end

Utilisation de creates

De nombreuses ressources Chef non idempotentes prennent également en charge un paramètre creates, qui explique ce que fait la ressource. En d'autres termes, qu'est-ce que le windows_batch "créer". Il peut s'agir d'un fichier, d'un répertoire ou d'un exécutable. Ainsi, le code suivant est équivalent à l'ancienne réponse.

windows_batch "Backup IIS Config" do
  code %Q|#{node['iis']['home']}"\\appcmd add backup BkpB4Chef|
  creates"#{node['iis']['home']}\\backup\\BkpB4Chef"
end

Pourquoi not_if vs l'encapsuleur conditionnel

Chef s'exécute en deux phases - la phase de compilation et la phase de convergence. Pendant la phase de compilation, les recettes sont évaluées et les ressources sont ajoutées à la collection de ressources. Dans la phase de convergence, les ressources de la collection de ressources sont exécutées et évaluées par rapport au système cible. Considérez donc l'exemple suivant:

if false
  service 'foo' do
    action :start
  end
end

Il s'agit d'une recette assez simple qui démarre un service basé sur certaines conditions. Cependant, à la fin de la phase de compilation, la ressource service n'est pas ajoutée à la collection de ressources. Puisque la recette DSL est instance_evaled, l'emballage if false conditionnel empêche ce code d'être lu par la machine virtuelle Ruby. En d'autres termes, c'est comme si ce service n'existait jamais.

Il est assez courant de notifier les ressources. Plus loin dans la recette, vous souhaiterez peut-être redémarrer Apache en raison d'un changement de configuration. La façon "appropriée" de procéder consiste à utiliser les notifications:

template '/var/www/conf.d/my.conf.file' do
  # ...
  notifies :restart, 'service[Apache2]'
end

Ce template ne peut pas notifier correctement la ressource de service, car il n'existe pas dans la collection de ressources. Cette recette échouera donc. Cela semble être un exemple trivial, mais si vous modifiez la conditionnelle if false à un test d'attribut de nœud:

if node['cookbook']['use_Apache']
  service 'Apache2' do
    action :start
  end
end

vous avez créé une dichotomie dans votre livre de cuisine où cela fonctionnera 50% du temps. Malheureusement, la plupart des livres de cuisine sont beaucoup plus complexes que deux ressources, de sorte que le nombre de cas Edge où une ressource peut notifier une ressource inexistante augmente considérablement avec la complexité. Tout cela est résoluble (et présente le comportement correct) en utilisant des gardes de ressources:

service 'Apache2' do
  action :start
  only_if { node['cookbook']['use_Apache'] }
end
27
sethvargo

Utilisation Dir.exists?. Vous pouvez également remplacer if ! condition par unless condition qui se lit un peu mieux.

unless Dir.exist? "#{node['iis']['home']}\\backup\\BkpB4Chef"
 windows_batch "Backup IIS Config" do
  code <<-EOH
   "#{node['iis']['home']}"\\appcmd add backup BkpB4Chef
  EOH
 end
end
6
jtblin