備忘録 Chef ファイルのバックアップを明示的に行いたい（notifies属性をうまく利用する）

#1. やりたいこと
Chefでcookbook_file,file,templateリソースを使うと、/var/chef/backupにファイルがバックアップされますが、Chefから知らない人からすると、そんなことなんてしったこっちゃない。
手作業でやるみたいに、明示的にファイルをコピーする処理をいれてみたいのである。

#2.コードを書く（その1）
/etc/hostsファイルを編集される場合、事前にバックアップを取得
そのために、notifies属性をうまく利用する

```ruby:test.rb
mtime = Time.now.strftime("%Y%m%d%H%M%S")
hosts_file = File.join("/etc",node['linuxos']['hosts'])

# backup /etc/hosts
bash "backup #{hosts_file}" do    
    code <<-EOH            cp -p #{hosts_file} #{hosts_file}.#{mtime}   
    EOH   
    action :nothing    
    only_if {File.exists?("#{hosts_file}")}
end

# edit hosts
template “edit#{hosts_file}" do    
    source "#{node['linuxos']['hosts']}.erb" 
    path  "#{hosts_file}"    
    mode '0644'    
    action :create    
    notifies :run,"bash[backup #{hosts_file}]", :before
end
```
- タイムスタンプは、RubyのTimeクラスをいきって使ってみる。
- bashリソースの中で、 action: nothing　を設定。この時点では、リソースは実行されない。
- template リソースの中で、 notifies :run,"bash[backup #{hosts_file}]", :before と設定。 :before　とすることで、template リソースが実行される前に、bash リソースが実行される。

#3.コードを書く（その2）
bashリソースを使わなくても、fileリソース使えばええやんけ！っていうのを後から知る。
なので、fileリソースを使う場合は、以下のような感じ。

```ruby:test.rb
mtime = Time.now.strftime("%Y%m%d%H%M%S")
hosts_file = File.join("/etc",node['linuxos']['hosts'])

file "#{hosts_file}.#{mtime}" do
    content IO.read( "#{hosts_file}" )
    action :nothing
end

# create hosts
template "create #{hosts_file}" do
    source "#{node['linuxos']['hosts']}.erb"
    path  "#{hosts_file}"
    mode '0644'
    action :create
    notifies :run,"file[#{hosts_file}.#{mtime}]", :before
end
```

すっきりしましたね。
 ※実行ログ

---

```console
$ sudo chef-solo -c /home/chef/chef-repo/solo.rb -o "recipe[linuxos::crt_hosts]"
Starting Chef Client, version 13.6.4
[2017-11-30T20:02:12+09:00] WARN: Run List override has been provided.
[2017-11-30T20:02:12+09:00] WARN: Run List override has been provided.
[2017-11-30T20:02:12+09:00] WARN: Original Run List: []
[2017-11-30T20:02:12+09:00] WARN: Original Run List: []
[2017-11-30T20:02:12+09:00] WARN: Overridden Run List: [recipe[linuxos::crt_hosts]]
[2017-11-30T20:02:12+09:00] WARN: Overridden Run List: [recipe[linuxos::crt_hosts]]
resolving cookbooks for run list: ["linuxos::crt_hosts"]
Synchronizing Cookbooks:
  - linuxos (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 2 resources
Recipe: linuxos::crt_hosts
  * file[/etc/hosts.20171130200216] action nothing (skipped due to action :nothing)
  * template[create /etc/hosts] action create (up to date)
  * template[create /etc/hosts] action create (up to date)
[2017-11-30T20:02:16+09:00] WARN: Skipping final node save because override_runlist was given
[2017-11-30T20:02:16+09:00] WARN: Skipping final node save because override_runlist was given

Running handlers:
Running handlers complete
Chef Client finished, 0/3 resources updated in 05 seconds
```

---


#4.notifies応用編
ファイルを編集した後に、サービスを再起動したいような場合、notifies属性をうまく利用すれば、必要に応じて、サービスの再起動が可能となる。


```ruby:test.rb
mtime = Time.now.strftime("%Y%m%d%H%M%S")
conf_file = File.join(node['linuxos']['ssh_dir'],node['linuxos']['sshd_conf'])

# backup /etc/sshd/sshd_config
file "#{conf_file}.#{mtime}" do
    content IO.read( "#{conf_file}" )
    action :nothing
end

# create conf file
template "create #{conf_file}" do
    source "#{node['linuxos']['sshd_conf']}.erb"
    path  "#{conf_file}"
    mode '0600'
    action :create 
    notifies :run,"bash[backup #{conf_file}]", :before
    notifies :restart,"systemd_unit[sshd]", :delayed
end


# sshd restart
systemd_unit 'sshd' do
    action :nothing
end
```
- notifies :restart,"systemd_unit[sshd]", :delayed このdelayedを設定することで、templateリソースで編集があった後に、systemd_unitリソースが実行される。