備忘録、はじめました。

作業したこと忘れないようにメモっておきます。

Chefで複数リソースに更新があった時だけbashを実行

はじめに

cookbookのfilesの中に大量のtomlファイルが入っていて、各tomlファイルに対してコマンドを実行したい場面に直面しました。 ファイルの更新が合った時だけ、そのコマンドを実行したかったので、その時の作業をメモします。

目的

  • confファイルが更新されているかをチェック
  • 更新されていればファイルを差し替えしてスクリプトを実行

作業

作業環境は、仮想マシンにChef-ServerとChef-Clientを用意し、作業(knifeを実行するマシン)はホストマシンになります。 下記、レシピになります。

recipe.rb

files = run_context.cookbook_collection["my-cookbook-name"].file_filenames
files.select!{ |file| file =~ /\.toml/ }

files.each do |file| 
  # 2. 配置したtomlを使ってコマンドを実行
  bash "exec-#{File.basename(file,".*")}" do
    action :nothing # 実行しない
    user "vagrant"
    cwd "/home/vagrant/conf"
    code "echo #{File.basename(file,".*")} >> /home/vagrant/exec-stamp.txt" # 処理したいコマンド
  end
end

files.each do |file| 
  # 1. tomlを配置
  cookbook_file "/home/vagrant/conf/#{File.basename(file)}" do
    owner "vagrant"
    group "vagrant"
    mode 0644
    source File.basename file
    not_if { FileUtils.cmp("/home/vagrant/conf/#{File.basename(file)}", file) } # ファイルの比較
    notifies :run, "bash[exec-#{File.basename(file,".*")}]" # bash[exec-hoge] の内容を実行しにいく
  end
end

さいごに

filesの中の一覧を取得する方法を見つけるのに時間がかかってしまった。取得方法は、run_context.cookbook_collection["cookbookの名前"]で、/var/chef/以下に保存されているファイルの絶対パスが配列で返って来ます。