クックブックにデフォルトの属性があるとしましょう:
_default.nginx_upstreams = {
'service1' => ['service1.server.com'],
'service2' => ['service2.server.com'],
}
_
その後、最終的に私のレシピに到達するまで、ロールと環境で変更およびオーバーライドされます。そこで、属性に追加したい追加のサービスを計算します。私がこのようなことをしたら:
_node.nginx_upstreams.merge! {'service3' => ['service3.server.com']}
_
テンプレートで属性を使用しようとすると、テンプレートで_undefined method 'each' for nil:NilClass
_を取得しようとします
_<% node.nginx_upstreams.each do |name, servers| %>
_
さらに、_WARN: Setting attributes without specifying a precedence is deprecated and will be removed in Chef 11.0
_も取得します。有用な警告は、属性を通常の優先順位で設定する方法を教えてくれます(明らかに_node.set["key"] = "value"
_を使用しますが、デフォルトの指定方法や属性のオーバーライド方法は教えてくれません)。
この問題を回避するには、次のようにします。
_upstreams = node.nginx_upstreams.to_hash
upstreams.merge! {'service3' => ['service3.server.com']}
template "nginx_config" do
variables({:upstreams=>upstreams})
end
_
しかし、それはハックのように感じます。 このページ を超えてnode.set()
に関するドキュメントを見つけることができません。しかし、方法を言いません。
それで...レシピ内からどのように属性(他のすべてと一緒に深くマージされる)を適切に設定しますか? node.set()
呼び出しは実際に何をしますか?マージしたい優先順位を伝えることができますか?
default.nginx_upstreams
はdefault[:nginx_upstreams]
およびdefault['nginx_upstreams']
と同じです-規則では、後者の2つのうち1つを使用します。また、文字列をさらに使用する場合は、ここでも使用します。
属性ファイルでnginx_upstreams
を初期化する方法は、次のようにするのと同じです。
default['nginx_upstreams']['service1'] = ['service1.server.com']
default['nginx_upstreams']['service2'] = ['service2.server.com']
そして、その前にdefault['nginx_upstreams'] = {}
を初期化する必要はありません。これらはハッシュではなく属性であり、はるかにスマートです。 :)
レシピ内からの属性の変更は次のように行われます。
node.default['nginx_upstreams']['service3'] = ['service3.server.com']
優先順位を変更する必要がある場合は、set
の代わりにoverride
またはdefault
を使用できます。優先名(node['nginx_upstreams']
またはnode.nginx_upstreams
)を省略すると、set
優先順位が使用されます。しかし、これは非推奨であり、すぐに削除されます-それが警告のすべてです。 属性に関するマニュアルページ をチェックしてください。すべてが実際にあるからです。
Chef属性についてさらに詳しく知りたいと思ったので、ノード属性のオーバーライドでこの質問を参照するユーザーにとって非常に重要です。
ファイルメソッドは属性に対応します
クックブックの属性ファイル内またはレシピ内で次のメソッドを使用します。これらのメソッドは、同じ名前の属性タイプに対応しています。
属性の優先順位
属性は常に、シェフクライアントによって次の順序で適用されます。
ここで、リストの最後の属性は、ノードに適用されるものです。
つまり、OHAI属性の優先順位が最も高く、クックブック属性ファイルのデフォルト属性の優先順位が最も低くなります。
注:ユーザーの利益のために、 属性 のChefドキュメントから重要な詳細を提供しました。 URLが移動されるか無効になる場合があるためです。
だから、掘り下げた後、私は答えを見つけました:
node.set
node.setはnode.normalのエイリアスであるため、node.setではなくnode.default
(またはnode.override)を使用します。通常のデータはノードオブジェクトに保持されます。したがって、node.setを使用すると、ノードオブジェクトにデータが保持されます。 node.setを使用するコードが後で削除され、そのデータが既にノードに設定されている場合、そのデータは残ります。
通常の属性とオーバーライド属性は、chef-clientの実行の開始時にクリアされ、その時点でのクックブックとレシピのコードに基づいて実行の一部として再構築されます。
node.set
(およびnode.normal
)は、最初のシェフクライアントの実行時にデータベースのパスワードを生成するなどの目的でのみ使用する必要があります。このタイプのデータを保存するには、データバッグの使用が推奨されるため、このような場合でも避ける必要があります。