chef で FileEdit を使うときは、write_file を使ってファイルを書き出さないほうが良い(かもしれない)
執筆時の chef のバージョンは以下のとおりです。
$ rpm -q chef chef-11.16.4-1.el6.x86_64
chef でファイルの変更をする場合、
chef/file_edit.rb at 11.16.4 · opscode/chef · GitHub
を使うことで簡単に行うことができます。
実際にコードを書く場合は、
file "/tmp/testfile" do f = Chef::Util::FileEdit.new(path) f.insert_line_if_no_match(/hogehoge/, "hogehoge") f.write_file end
のように記述することでファイルを変更することができます。
各メソッドを簡単に説明すると、
- insert_line_if_no_match は、第一引数の regex に match しなければ第二引数の文字列を追記する
- write_file は、元のファイルに .old をつけて mv して、新しくファイルを作り直す
です。
ただ、write_file はファイルを変更する上では問題ないのですが、
これを使うと chef 実行時に diff が出力されません。
ファイルをどのように変更したか確認したい場合に困ります。
また、chef の backup にも保存されません。
実際に実行すると以下の様なログが出力されます。
* file[/tmp/testfile] action create (up to date)
up to date と出力されていますが、
実際はファイルに文字列が追記されています。
これを解決する方法は、Chefのレシピでsed的な事を実施 - Qiita が参考になりました。
ありがとうございます。
https://github.com/opscode/chef/blob/11.16.4/lib/chef/util/file_edit.rb#L27
の @editor.lines には、ファイルの行が配列で格納されているので、
send(:editor).lines で取得して、join で結合してファイルに出力する、といった方法のようです。
コードにすると以下のようになります。
file "/tmp/testfile" do f = Chef::Util::FileEdit.new(path) f.insert_line_if_no_match(/hogehoge/, "hogehoge") content f.send(:editor).lines.join end
この場合、content を使ってファイルを変更するため、
diff が出力されますし、backup にも保存されます。
write_file があるので、そちらを使ったほうが良さそうな感じはしますが、
diff と backup のことを考えると content を使って内容を上書きする方法が良さそうです。