Posted at
PuppetDay 5

PuppetのHieraで同じリソースを複数定義する(create_resources)

More than 3 years have passed since last update.

Puppet Advent Calendar 2015の、5日目です。

Puppetをもりあげていこうということで、参加させてもらいます。


Hieraで同じリソースを複数定義する

Puppetで同じリソースを複数定義したい場合があったりします。

例えば、Apacheのvirtual hostの設定を/etc/httpd/conf.d/の配下に個別に置く定義を何度も使いたいとか、ユーザのアクセス設定をする定義をユーザごとに使いたいとか(ftpの/etc/vsftpd/user_conf/をユーザごとに定義するとか)。

Hieraを使った場合でも、create_resourcesを使うと、同じ定義を何度も使うことができたりします。


create_resources

create_resourceは、ハッシュ情報を指定したリソースに変換する関数です。パラメータに、リソースタイプとハッシュ情報(リソースへのパラメータをハッシュ形式で書いたもの)を指定すると、指定したリソースを複数定義できます。


既存リソースでの例

まずは既存リソースで使う例です。例えば、groupリソースとuserリソースをHieraで直接複数定義したい場合、まず次のようなクラス用意します。


/etc/puppet/modules/base/manifests/account.pp

class base::account (

) {

$groups = hiera('base::account::groups', {})
create_resources('group', $groups)

$users = hiera('base::account::users', {}) # (1)
create_resources('user', $users) # (2)

}


(1)はHieraの定義から、base::acount::usersの情報をハッシュとして\$usersに格納する行で、(2)はハッシュ情報(\$users)をcreate_resourcesでuserリソースに変換する行です。base::acount::usersや\$usersは変数名を適当に付けているだけなので、好みな変数名でかまいません。

Hiera側は下記のように書きます。ユーザやグループのパラメータをハッシュ形式で列挙するだけです。AnsibleをYAML形式で書いた場合にちょっと似てます。base::account::groupsとbase::account::usersがさきほどのbase::accountクラスにわたって、create_resourcesでリソース定義に変換されます。


/etc/puppet/hieradata/sample.yaml

---

classes:
- base::account

base::account::groups:
hoge:
ensure: 'present'
gid: '1002'
fuga:
ensure: 'present'
gid: '1003'
base::account::users:
hoge:
ensure: 'present'
gid: '1002'
home: '/home/hoge'
shell: '/bin/bash'
uid: '1002'
fuga:
ensure: 'present'
gid: '1003'
home: '/home/fuga'
shell: '/bin/bash'
uid: '1003'


ちなみに、上の定義は次のマニフェスト定義と等価です。

group { 'hoge':

ensure => 'present',
gid => '1002',
}

group { 'fuga':
ensure => 'present',
gid => '1003',
}

user { 'hoge':
ensure => 'present',
gid => '1002',
home => '/home/hoge',
shell => '/bin/bash',
uid => '1002',
}

user { 'fuga':
ensure => 'present',
gid => '1003',
home => '/home/fuga',
shell => '/bin/bash',
uid => '1003',
}


defineしたリソースでも

ちなみに、既存のリソースだけでなく、defineで独自に作ったリソースでも同様です。例えば、/user/vsftpd/user_conf/ユーザ名を、次のようなHiera定義で指定するには、


/etc/puppet/hieradata/sample.yaml

---

classes:
- vsftpd::config_user_conf

vsftpd::config_user_conf::hash:
hoge:
user: 'hoge'
content: 'local_root=/home/ftp/hoge'
fuga:
user: 'fuga'
content: 'local_root=/home/ftp/fuga'


このような"/etc/vsftpd/user_conf/ユーザ名"を配布するリソースをdefineして、


/etc/puppet/modules/vsftpd/manifests/def_user_conf.pp

define vsftpd::def_user_conf(

$user,
$content,
){

file { "/etc/vsftpd/user_conf/${user}":
content => $content,
owner => 'root',
group => 'root',
mode => '644',
}

}


create_resourcesで展開する、ラッパークラスみたいなものを用意すればよいです。


/etc/puppet/modules/vsftpd/manifests/config_user_conf.pp

class vsftpd::config_user_conf (

) {

$user_conf_hash = hiera('vsftpd::config_user_conf::hash', {})
create_resources('vsftpd::def_user_conf', $user_conf_hash)

}


実際にPuppet適用後の結果はこんな感じです。

[root@localhost ~]# grep local /etc/vsftpd/user_conf/*

/etc/vsftpd/user_conf/fuga:local_root=/home/ftp/fuga
/etc/vsftpd/user_conf/hoge:local_root=/home/ftp/hoge


もしかすると

Puppet4から強化されたループの文法を使う方が主流になるかもしれませんが、こんなやり方もあったりします。


参考