オープンソースなシステム自動管理ツール Puppet

第5回マニフェスト応用編(その2)

前回に引き続き、マニフェストについてより詳しく見て行きたいと思います。

メタパラメータ

リソースで指定できるパラメータには、特定のリソースタイプに固有なパラメータだけではなく、すべてのリソースタイプで指定できるパラメータがあります。このようなパラメータをメタパラメータと呼びます。

リソースの依存関係を宣言するbefore、require、notify、subscribeはメタパラメータです。他にも様々なメタパラメータがあります。メタパラメータにどのようなものがあるかは、Puppet日本語WikiのTypeリファレンスをご参照ください。

変数

マニフェストでは以下のように、変数の割り当てと参照が可能です。

$default_owner = 'root'
$default_group = 'root'

file { '/etc/hosts':
    owner => $default_owner,
    group => $default_group,
    mode => 644,
    source => 'puppet://server/module/hosts',
}

{}によって変数のスコープが形成され、同一スコープ内で一度割り当てられた変数の変更はできません。例えば、以下のようにマニフェスト中で変数の値を変更してみます。

$owner = 'root'
$owner = 'nobody'

すると、puppetdがマニフェストを取得する際に、以下のようなエラーが表示されます。⁠puppetmasterdの起動時には表示されませんので、ご注意ください。)

err: Could not retrieve configuration: Cannot reassign variable owner at /etc/puppet/manifests/site.pp:7

以下のようにサブスコープ内であれば、変数の値を上書きすることができます。

$owner = 'root'

define testing {
    $owner = 'nobody'
}

Facter変数

Facter変数は、Facterというライブラリによって自動でセットされる変数です。このライブラリは、システムに関する情報(プロセッサアーキテクチャ、利用OSとそのバージョン、ドメイン名、FQDN、IPアドレスなど)を収集するための、クロスプラットフォームなRubyライブラリです。

Facter変数には以下の表のようなものがあります。

Facter変数名変数値の例
$operatingsystemCentOS
$fqdnpuppet.example.org
$hostnamepuppet
$domainexample.org
$kernelLinux
$kernelrelease2.6.18-8.el5
$ipaddress192.168.115.129
$macaddress00:0C:29:94:8A:DA
$memorysize1024.00 MB
$memoryfree217.10 MB
$processor0Intel(R) Pentium(R) D CPU 2.80GHz
$processorcount1

ご利用のシステム上でどんなFacter変数が取得できるかは、以下のようにfacterコマンドを実行してみるとわかります。

$ facter
architecture => i386
domain => example.org
facterversion => 1.3.7
fqdn => puppet.example.org
...

配列

以下のような記述で配列を定義することができます。

[ 'one', 'two', 'three' ]

配列の利用例は以下のようになります。この例では、ntpdというserviceリソースが、ntpd.confというfileリソース、ntpというuserリソース、ntpというpackageリソースに依存していることを宣言しています。

service { 'ntpd':
    ensure  => running,
    require => [ File['ntpd.conf'], User['ntp'], Package['ntp'] ],
}

条件指定

セレクタ

セレクタは条件によって変数の値を変える場合に利用します。以下の例では、Facter変数$operatingsystemがFreeBSDの場合、変数$sudoにはsecurity/sudoが割り当てられ、その他の場合には$sudoにはsudoが割り当てられます。

$sudo = $operatingsystem ? {
    freebsd => 'security/sudo',
    default => 'sudo',
}

package { "$sudo": ensure => latest }

case

セレクタは条件によって変数の値を変えるために利用しますが、caseは条件によって宣言するリソースを変えたり、実行する関数を変えたりする場合に利用します。

以下の例では、OpenBSDではデフォルトでsudoが入っているため特になにもせず、その他のOSの場合にはpackageリソースを宣言して、sudoパッケージをインストールします。

case $operatingsystem {
    openbsd: {}
    default: {
        package { 'sudo':
            ensure => present
        }
    }
}

以下の例では、OS毎にincludeするクラスを変更しています。

case $operatingsystem {
    sunos:   { include 'solaris' }
    redhat:  { include 'redhat'  }
    default: { include 'generic' }
}

if/else

if/elseでは、単純なブール値での真偽判断のみが可能です。以下の例では、$booleanが真の場合には/some/fileが存在するというリソースの状態を宣言し、偽の場合には/some/other/fileが存在するというリソースの状態を宣言します。

if $boolean {
    file { '/some/file': ensure => present }
} else {
    file { '/some/other/file': ensure => present }
}

関数

Puppetは多くの組み込み関数をサポートしています。関数にはstatementタイプとrvalueタイプの2種類があります。 statementタイプの関数は独立して実行するもので、返り値はありません。以下のnotice関数はstatementタイプであり、引数で指定された文字列をログやコンソールに出力します。

notice('Something weird is going on')

以下のように関数はカッコなしても実行できます。

notice 'Something weird is going on'

template関数はrvalueタイプであり、テンプレートmytemplate.erbを評価した結果を返します。そのため、ファイル/my/fileの内容が、テンプレートmytemplate.erbの評価結果で置き換えられます。

file { '/my/file': content => template('mytemplate.erb') }

Puppetで利用可能な関数については、Puppet本家WikiのFunction Referenceをご参照ください。

クォート

マニフェストでは、英数字と-⁠ハイフン)のみで構成され、英数字ではじまる文字列は、クォートしなくても文字列として扱われますが、必ずクォートすることが推奨されています。

シングルクォートされた文字列は変数展開されませんので、以下の例では、変数$valueの値は$oneという文字列になります。

$value = '$one'

ダブルクォートされた文字列は変数展開されますので、変数$valueには変数$oneの値が割り当てられます。

$value = "$one"

変数に使われている文字列と他の文字列を明確に区別したい場合には、以下のように記述します。

$value = "${one}two"

予約語

true、false、define、inherits、classといった文字列は予約語であるため、文字列として利用する場合には、必ずクォートすることが推奨されます。

コメント

マニフェストではshスタイルのコメントをサポートしており、#以降の文字列はコメントとみなされます。

# OS毎にsudoのパッケージ名を変更する
$sudo = $operatingsystem ? {
    freebsd => 'security/sudo',
    default => 'sudo',
}

マニフェストのインポート

以下のように、importキーワードにより他のマニフェストをインポートすることができます。インポート対象のファイル名はワイルドカードで指定することもできます。

import 'other.pp'
import 'classes/*'
import 'packages/[a-z]*'

まとめ

マニフェストについての解説は今回で終了です。これでマニフェストについての必要な知識は一通り得られたことと思います。次回からは、より実践的なPuppetの利用方法について解説していきたいと思います。

参考URL

おすすめ記事

記事・ニュース一覧