Puppet4.xではじめるサーバ設定自動化 5（リンク）

Puppet4.xではじめるサーバ設定自動化の、シンボリックリンク編です。
全体的な目次は、[ここ](http://qiita.com/kijibato/items/ae510dfa91884bdd9f61)を参照してください。
主にCentOS 7を例に紹介しているので、その他OSについては読み替えてください。

# リンク作成
## 基本

リンクを作成する場合、Puppetのマニフェストでfileリソースで定義します。
ディレクトリを作る時もfileで、リンクを作る時もfileです。
**ディレクトリかリンクかは、ensure属性をdirectoryにするかlinkにするかで変わります。**

/tmp/puppet_link_sampleを作る場合の例です。リンク元が/tmp/puppet_link_sample、リンク先/var/log/puppet_link_sampleにする場合、次のように定義します。

```puppet:link01.pp
file { "/tmp/puppet_link_sample" :
  ensure => "link",
  target => "/var/log/puppet_link_sample/",
}

```

- fileの右側のタイトルにリンク元のパスを指定
- リンクの場合、ensure属性にlinkを指定
- target属性は、リンク先

## リンク先は別途定義する
リンク先が必要な場合は、別途定義する必要があります。
リンク先がディレクトリ(/var/log/puppet_link_sample/)の場合。

```puppet:link02.pp
file { "/tmp/puppet_link_sample" :
  ensure => "link",
  target => "/var/log/puppet_link_sample/",
}

file { "/var/log/puppet_link_sample/" :
  ensure => "directory",
  owner  => "root",
  group  => "root",
  mode   => "0755",
}

```

## リンク元がすでにディレクトリかファイルの場合
リンク元のパスが、すでにディレクトリかファイルの場合、force属性をtrueにしないとリンクは作成できません。ただし、**強制的にリンクに置き換えるため、リンクに置き換える前のパスに重要なデータがないか注意しましょう。**

```puppet:link03.pp
file { "/tmp/puppet_link_sample" :
  ensure => "link",
  target => "/var/log/puppet_link_sample/",
  force  => "true",
}

```

- force属性に、trueを指定

### force属性なしの実行例
リンクを作りたい場所にすでにディレクトリがある場合、かつforce属性なしの実行例です。まずnoopです。例によって、エラーは出ません。

```
# /opt/puppetlabs/bin/puppet apply link01.pp -t --noop
Notice: Compiled catalog for c82e3a71e41e in environment production in 0.04 seconds
Info: Applying configuration version '1461425393'
Notice: /Stage[main]/Main/File[/tmp/puppet_link_sample]/ensure: current_value directory, should be link (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Applied catalog in 0.02 seconds
```

ただ、実際に実行すると、すでにあるファイルは消せないので、リンクに変えるの失敗しました的なエラーがでます。正直noopの時点で出して欲しかったりしますが。。。

```
change from directory to link failed: Could not remove existing file
```

```
# /opt/puppetlabs/bin/puppet apply link01.pp -t       
Notice: Compiled catalog for c82e3a71e41e in environment production in 0.05 seconds
Info: Applying configuration version '1461425405'
Notice: /Stage[main]/Main/File[/tmp/puppet_link_sample]: Not removing directory; use 'force' to override
Notice: /Stage[main]/Main/File[/tmp/puppet_link_sample]: Not removing directory; use 'force' to override
Error: Could not remove existing file
Error: /Stage[main]/Main/File[/tmp/puppet_link_sample]/ensure: change from directory to link failed: Could not remove existing file
Notice: Applied catalog in 0.02 seconds
```

### force属性trueの実行例

リンク元にディレクトリがあった場合の実行例。まず、noopから。

```
# /opt/puppetlabs/bin/puppet apply link03.pp -t --noop
Notice: Compiled catalog for c82e3a71e41e in environment production in 0.04 seconds
Info: Applying configuration version '1461425425'
Notice: /Stage[main]/Main/File[/tmp/puppet_link_sample]/ensure: current_value directory, should be link (noop)
Notice: Class[Main]: Would have triggered 'refresh' from 1 events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Applied catalog in 0.02 seconds
```

force属性をtrueにした場合、ディレクトリをlinkに変えたよ的なログがでて、リンクが作成できます。

```
ensure changed 'directory' to 'link'
```

```
# /opt/puppetlabs/bin/puppet apply link03.pp -t       
Notice: Compiled catalog for c82e3a71e41e in environment production in 0.04 seconds
Info: Applying configuration version '1461425494'
Info: /Stage[main]/Main/File[/tmp/puppet_link_sample]: Recursively backing up to filebucket
Notice: /Stage[main]/Main/File[/tmp/puppet_link_sample]/ensure: ensure changed 'directory' to 'link'
Notice: Applied catalog in 0.02 seconds
```
## リンク元をリンク先に移動させたい場合
もし、リンク元のディレクトリをリンク先に移動させてから、リンクを作成したい場合の例です。**Puppet4.xでは、デフォルトではマニフェスト記載順で処理されます。Puppet3.xでは処理順に注意が必要です。**

なおサンプルなので、もしかすると移動したいディレクトリのサイズが大きすぎる場合、うまくいかないかもしれません(execリソースの、タイムアウトがデフォルト300秒なので)。**重要なデータを扱う場合は、手作業で、あらかじめバックアップしたり、移動する方がよい場合もあります。**

```puppet:link04.pp
#(1)
exec { "mv /tmp/puppet_link_sample /var/log/" :
  command  => "mv /tmp/puppet_link_sample /var/log/",
  creates  => "/var/log/puppet_link_sample",
  path     => "/usr/bin",
}

#(2)
file { "/tmp/puppet_link_sample" :
  ensure => "link",
  target => "/var/log/puppet_link_sample/",
}

```

- (1)
  - execリソースは、コマンドを実行するときに使う
  - command属性に、実行するmvコマンド
  - creates属性で、mv先(/var/log/puppet_link_sample)にファイルがなければコマンドを実行するように
  - path属性で、コマンドのパス設定
- (2)
  - fileリソースでリンクを作成

# リンクを作るケース
リンクを作るケースとして、よくあるのがデフォルトのログの出力先を変えるとかです。デフォルトだとシステム領域と同じパーティションにログをはくようになっていた場合、ログが一杯になると危険なので、別パーティションにログをはかせるようにします。

そのとき、元のパスにディレクトリかファイルがあったりするので、元のパスを移動させてから、リンクを張る場面があります。ただ、上でも書きましたが、しばらく稼働して重要なデータある場合は、慎重に。

# 参考

fileリソースの詳しい情報は、下記参照です。
(リンクについてまとまっていないため、linkで検索してください)

- https://docs.puppet.com/puppet/latest/reference/type.html#file