基于厨师版本的食谱依赖关系

时间:2019-03-15 18:24:00

标签: ruby chef metadata chef-recipe

我有一个包装食谱,它使用其他食谱中的资源,但是它们有不同的约束。我尝试如下定义我的metadata.rb:

Theorem plus_id_example : forall n m : nat,
  n = m =>
  n + n = m + m.

这不起作用,因为厨师在融合过程中同时抓住了两本食谱。我尝试了几种不同的语法(only_if,除非,等等。。。),但没有一个奏效。任何人都有解决此问题的想法吗?

1 个答案:

答案 0 :(得分:1)

TL; DR

您使用的是Chef DSL的约束,其使用方式不希望使用。您需要基于布尔表达式而不是元数据约束进行分支。我提供了几种使用String#to_f作为示例的方法(如果您关心语义版本控制中的补丁程序级别,则不建议这样做),以及更准确但经常被忽略的Gem::Version

不要对分支使用约束

  

if chef_version '<= 12'

您正在尝试使用来自DSL的约束。此约束has a specific purpose:声明食谱支持的厨师客户端版本,而不提供逻辑分支。如果不查看DSL的基础Chef代码,我会说该表达式不太可能以您期望的方式提供if-then表达式。暂时暂不考虑这是否是正确的模式,您可以尝试通过两种不同的方式来获取当前版本的Chef工具:

  1. 在chef-client版本上分支,可能转换为Float(通常是String)。例如:

    if Chef::VERSION.to_f <= 12
    
  2. 从ohai获取节点值,例如:

    if node['chef_packages']['chef']['version'].to_f <= 12
    
  3. 直接从客户端解析值,例如:

    depends %x(chef-client --version).split[1].to_f <= 12 ? 'ypg_tomcat' : 'yp_tomcat'
    

但是,在所有情况下,您都必须处理一个事实,即正在传递包含语义版本而不是Float或Integer的String。因此,您必须弄清楚您是如何真正地解析信息的,这很容易出错(不过,请参见下文,了解使用Gem :: Version的技巧)。无论如何,一旦按照所需的方式对其进行了解析,就可以使用比较运算符对其进行匹配,以获取所需的分支行为。

更好的选择

您可能不应该尝试使元数据约束保持业务逻辑,而应该将数据移到属性中。考虑诸如node['yp_linko']['tomcat_cookbook']之类的属性,您可以根据语义版本控制以外的其他可检测节点值来设置该属性。

另一种方法是先声明两个食谱都具有依赖性,然后include将要在 yp_linko 食谱中的食谱内声明。例如,假设您尚未在Tomcat食谱中声明不兼容的Chef-Client版本:

# metadata.rb
depends 'yp_tomcat'
depends 'ypg_tomcat'

# default.rb
if Chef::VERSION <= Gem::Version.new(12)
  include ypg_tomcat::default
else
  include yp_tomcat::default
end

最后,您应该首先考虑在基础架构中运行不同版本的Chef客户端是否真的有意义。可能有业务需要这样做,但这是您实际上要解决的真正问题。在您的食谱中进行分支是针对基础结构问题的X / Y解决方案。看来您可能还会遇到其他类似问题的食谱,因此至少值得考虑的是让所有客户都使用同一版本而不是在食谱层面解决问题是否更有意义。