puppet の言語構造

Installation Guide を読めば、とりあえず puppet を動かすことはできるけど、やりたいことをやろうと思ってもすぐにできるわけでもない。というわけで、ドキュメントをちゃんと読んでみることにした。

まずは puppet の設定ファイルで使われている内部言語の理解から、ということで、Language Structures を超意訳してみる。

Types

puppet 設定の基本構成単位。管理されるコンピュータ上のオブジェクト(ファイルとかパッケージとか)を表すもので、あらかじめ用意されたビルトインタイプ以外にも、自ら定義することも可能。

file { "/etc/passwd": owner => root, mode => 644 } 
package { apache: install => true }

詳しくは Type Reference を参照。

Assignment

変数が利用できる。

$variable = value
$x = foo
$y = bar
$z = "$x$y"

Bringing Config files together

設定ファイルに、別の設定ファイルをインポートできる。

import "filename"

正規表現も利用可能。

import "classes/*"
import "packages/[a-z]*"

Scope

{ } によってスコープが形成される。

変数は一度割り当てられると、同一スコープ内では変更できないが、サブスコープ内では同一名の変数を割り当てることができる。

$var = value

# override $var
define testing {
    $var = othervalue
}

Components

ここでいう Components とは、自分で定義する Type のことっぽい。Components の定義と利用は以下の様な感じ。

define svnserve($source, $path, $user = false, $password = false) {
    file { $path:
        create => directory,
        owner => root,
        group => root
    }
    $svncmd = $user ? {
        false => "/usr/bin/svn co --non-interactive $source/$name .",
        default => "/usr/bin/svn co --non-interactive --username $user --password '$password' $source/$name ."
    }   
    exec { $svncmd: 
        cwd => $path,
        require => file[$path],
        creates => "$path/.svn"
    }   
}

svnserve { dist:
    source => "https://reductivelabs.com/svn",
    path => "/dist",
    user => "puppet",
    password => "password"
}

svnserve { "dist/config/apps/puppet":
    source => "https://reductivelabs.com/svn",
    path => "/etc/puppet",
    user => "puppet",
    password => "password"
}

利用する時はビルトインタイプと構文上の違いはない。

Server Classes

Class を定義してインクルードすることができる。

class  [inherits ] { ... }

継承も可能。

# really simple example
class solaris {
    file {
        "/etc/passwd": owner => root, group => root, mode => 644;
        "/etc/shadow": owner => root, group => root, mode => 440
    }
}

class solworkstation inherits solaris {
    file {
        "/etc/sudoers": owner => root, group => root, mode => 440;
        "/bin/sudo": owner => root, group => root, mode => 4111
    }
}

include solworkstation

以下の例だと、$operatingsystem の値と同名の Class と、$hostname に応じた Class がインクルードされる。

include $operatingsystem, $hostname ? {
    myhost => classA, default => classB
}

$operatingsystem とか $hostname とかは、Facterというライブラリを使ってプリセットされているみたい。

Classes vs. Components

Classes と Components の違いは以下の通り。

あと、Classes は引数を受け取れない、という違いもある。

Subclssing

Class は継承ができる。

class unix {
    file { "/etc/sudoers":
        owner => root,
        group => root,
        mode => 440
    }
}

class bsd inherits unix {
    File["/etc/sudoers"] {
        group => wheel
    }
}

Using Classes Outside of Puppet

puppet サーバで設定された Class 名が、puppet クライアントの /etc/puppet/classes.txt に保存されるので、それを外部プログラムなどから読み込んで利用したりできるよ、とうことらしい。

FC4 で yum insall した puppet の場合は、/var/lib/puppet/classes.txt に保存されていた。

Nodes

node  { ... }

特定のホストに適用する設定を割り当てる。

以下の例だと、file type はすべてのホストに割り当てられるけど、webserver class と dbserver class の中に書かれた設定は、それぞれ特定のホストにのみ割り当てられる。

class webserver { ... }
class dbserver { ... }

file { "/etc/sudoers": mode => 440 } # apply to everyone

node host1, host2 {
    include webserver
}
node host3, host4 {
    include dbserver
}

node は継承することも可能。

node base {
    include $operatingsystem
}

node kirby inherits base {
    include webserver
}

FQDN で指定する時は、シングルクォートで囲む。

node 'host.domain.com' {
    ...
}

Conditionals

条件指定が可能。

以下の例は $os が何かによって、 $owner に入る値が変わる。

define testing(os) {
    $owner = $os ? {
        sunos => adm,
        redhat => bin,
        default => root
    }
    file { "/some/file": owner => $owner }
}

以下の例は $operatingsystem が何かによって、適用する class が変わる。

case $operatingsystem {
    sunos:      { solaris {} } # apply the solaris class
    redhat:     { redhat  {} } # apply the redhat class
    default:    { generic {} } # apply the generic class
}

Reserved words

true, define, inherits, class は予約語。

Comments

sh スタイルのコメントが利用可。