厨师包装食谱最佳实践

时间:2015-02-11 23:30:04

标签: chef

在学习厨师时,我看到了包装食谱的冲突模式。例如。

有些cookbook使用default.rb,有些则使用customize.rb进行覆盖。

attributes/default.rb

attributes/customize.rb 

哪种是最佳做法?

另外,一些包装器cookbook在recipes / default.rb文件中有这样的参数:

normal['foo']['bar'] = 42

而其他人有

default['foo']['bar'] = 42

有些人

node.set['foo']['bar'] = 42

此外,一些食谱使用符号和其他字符串

['foo']['bar']
[:foo][:bar]

我应该使用哪种款式?

更新

看起来厨师已经发布了官方风格指南,该指南至少解决了部分问题(例如符号与字符串)。 https://docs.chef.io/ruby.html#

2 个答案:

答案 0 :(得分:10)

我还没有看到任何关于如何覆盖包装器烹饪书中的属性的正式最佳实践,我认为必须选择一种风格,只要你的所有烹饪书在你的组织中都是一致的,你应该是好的。以下是我的观点。


属性文件

我们最初遵循分离属性文件的方式,类似于您描述的attributes/customize.rb格式。但是,我们发现在attributes/default.rb中保留所有属性要简单得多,特别是因为我们的属性保持在50行代码之下。

覆盖优先顺序

我们总是在覆盖菜谱中覆盖属性时使用lowest attribute precedence。我们尽可能坚持default,因为优先顺序决定了您的食谱default胜过包装食谱default

属性访问样式

你看到的大多数食谱都使用字符串访问格式。

default['foo']['bar'] = 42

事实上,foodcritic rule特别禁止使用符号访问。 Foodcritic还鼓励使用consistent style for accessing attributes。如果你决定一种风格,请记住社区已经决定了字符串访问格式。

然而,还有另一种方式。 Chef中的属性不是Hash,它们实际上是MashMash恰好支持以方法形式访问属性,因此:

default.foo.bar = 42

我们更喜欢这种语法,因为它更紧凑。

但是,谨慎,Tejay Cardon points out,Chef使用method_missing实现了这一点,因此如果属性名称与当前(或将来)node相同,则可能会遇到问题对象方法。我们用我们的组织名称为我们的所有食谱做准备,因此不太可能发生碰撞,但是当我们覆盖社区食谱时,我们可能会遇到问题。值得庆幸的是,测试应该抓住任何这样的失误。

警示说明

包装器手册中的覆盖属性不会以令人惊讶的方式工作,尤其是涉及字符串插值时。这在this blog post中得到了很好的解释。主要要点是如果食谱将属性定义为:

default['version'] = '1.0'
default['url'] = "http://example.com/#{node['version']}.zip"

在您的包装食谱中,您覆盖version

default['version'] = '2.0'

default['url']仍将按照您的预期解析为http://example.com/1.0.zip,而不是http://example.com/2.0.zip。发生这种情况是因为在您的覆盖发生之前内插 url属性。博客文章更深入,并提供了一个潜在的解决方案。

总结

在一天结束时,有多种方法可以在Chef中做事,社区仍然日趋成熟。有关编写可重复使用的烹饪书等的一些最佳实践,但这些实践仍在不断发展。

你能做的最好的事情就是尝试各种风格,找出最适合你和你的团队的风格。一旦你决定了一种风格,我建议把风格指南放在一起(我用过this Angular style guide as inspiration)。您还可以使用custom foodcritic rules强制执行样式指南。我们用这种方法取得了成功。

答案 1 :(得分:3)

遗憾的是,那里的最佳实践很少,但有一些问题值得注意。

属性加载顺序

属性文件以非常具体的(尽管不是很清楚)顺序加载(执行)。

  1. 根据运行列表中引用的每个cookbook的运行列表和元数据以及所有依赖项来解析所需的cookbook。
  2. 一旦编制了所涉及的食谱清单,就会以书法形式订购。
  3. 然后以书法形式订购每本食谱的属性文件。
  4. 执行从列表的to开始,但是,如果遇到include_attribute语句,该属性文件将立即执行(并从列表中删除,以便第二次不执行。)< / LI>

    这很重要,因为如果同一个属性设置在同一级别,即default多个属性文件,那么最后一个要执行的文件将决定哪个值获胜。 __So总是include_attribute来自您的库菜谱的属性文件位于包装器菜谱的属性文件的顶部。然后在default级别设置属性(这样可以更容易地在其他地方覆盖它们)。

    其中一件事与其他事情不同

    普通属性(node.set或node.normal)是一个有趣的野兽。他们在厨师之间坚持不懈。因此,一旦您将属性设置为正常,它将一直存在,直到您删除它或更改它。有时这是一件好事,就像你想要记住的uuid,但有时这是一个意想不到的副作用。

    风格

    符号和字符串,方法,哦,我的。

    关于node.attributenode[:attribute]node['attribute']访问样式存在很多争论。如果你想看到硬币的两面,请阅读foodcritic 001。在我看来,node['attribute']已经赢得了大多数社区食谱开发者的支持,但它是一个非常苗条的多数。 node.attribute几乎普遍不受欢迎,因为它可能有邪恶的副作用。最终,你会使用你最喜欢的东西,但如果你的图书馆食谱相当一致,我建议你遵循他们的惯例。

    覆盖的地方

    就个人而言,我努力不要在属性文件之外设置属性。它经常导致头痛。将所有属性集操作保存在属性文件中会更容易,因此您可以轻松地将其删除。但是有些时候你要么不能在属性文件中做到这一点,要么在配方中更有意义。与大多数编程规则一样,您只需要权衡一致感。