
昨日直面していた問題の即時の解決策はわかっていますが (IRC #puppet の皆さんに感謝します)、それがどのように問題を解決したのか、またはむしろこの特定のシナリオにおけるクラスと定義の基本的な違いが何なのかがまだわかりません。
間違っていた元の定義:
define srv($name,$enable="true",$ensure="running",$provider="runit",$hasstatus="true",$hasrestart="true"){
exec {"sleep 5": path=>"/usr/bin:/usr/sbin:/bin:/sbin", before=>Service["$name"],}
service{"$name":
enable=>$enable,
ensure=>$ensure,
provider=>$provider,
hasstatus=>$hasstatus,
hasrestart=>$hasrestart,
}
}
エラー: リモート サーバーからカタログを取得できませんでした: サーバーでエラー 400: 定義が重複しています: Exec[sleep 5] は、ファイル /etc/puppet/modules/common/manifests/defines/srv.pp の 4 行目に既に定義されています。ノード testing.abc.def.com の /etc/puppet/modules/common/manifests/defines/srv.pp:4 で再定義できません
正しい定義:
define srv($enable="true",$ensure="running",$provider="runit",$hasstatus="true",$hasrestart="true"){
exec {"sleep 5 for $name": command=>"sleep 5", path=>"/usr/bin:/usr/sbin:/bin:/sbin", before=>Service["$name"],}
service{"$name":
enable=>$enable,
ensure=>$ensure,
provider=>$provider,
hasstatus=>$hasstatus,
hasrestart=>$hasrestart,
}
}
では、最初のケースでエラーが発生するのはなぜでしょうか? どのように定義を複製しているのでしょうか。言い換えると、この定義を使用するモジュールが 1 つだけであれば、最初の定義が機能するのでしょうか? ドキュメント内の Puppet 用語が私を混乱させているのかもしれません。しかし、大量の (動作する) モジュールを書いていて、これを理解していないのは危険に思えます。明確な回答が得られることを願っています。
答え1
Puppet 内のリソースは一意である必要があります。つまり、一意の名前を持つ必要があります。
説明したケースでは、定義にリソースがありExec["sleep 5"]
、呼び出すたびに srv
(基本的にはパラメーター化されたクラスを含めるのと同じです)、リソースExec["sleep 5"]
も含まれるため、パーサーは同じ名前の 2 つ以上のリソースを検出します。
$name
定義の をリソース名に追加することでExec
、リソースを一意にすることができます。少なくとも最も可能性が高いマニフェスト内の別の場所に同じ名前 ( Exec["sleep 5 for foo"
) の別のリソースがある場合、このエラーが再度発生するため、一意である必要があります。