Chef 条件资源参数

Chef conditional resource argument

我正在通过 Chef 创建用户。他的属性存储在数据包中:

{
    "id": "developer",
    "home": "/home/developer",
    "shell": "/bin/zsh",
    "password": "s3cr3t"
}

食谱是:

developer = data_bag_item('users', 'developer')

user developer['id'] do
  action :create

  supports :manage_home => true
  home developer['home']
  comment developer['comment']
  shell developer['shell']
  password developer['password']
end

问题是,如果 zsh 没有安装在节点上,我无法以 developer 身份登录。所以,我想有条件地为 user 资源应用参数,例如:

user developer['id'] do
  action :create

  supports :manage_home => true
  home developer['home']
  comment developer['comment']
  if installed?(developer['shell'])
    shell developer['shell']
  end
  password developer['password']
end

我怎样才能做到这一点?

实现您想要的最简单方法是明确检查 shell 是否存在:

shell developer['shell'] if File.exist? developer['shell']

为了补充@mudasobwa 的回答,在 chef 中以正确的方式进行回答,并避免错过 shell 如果它是由另一个食谱或同一食谱中的包资源安装的,您必须使用 lazy attribute evaluation .

长版供对如何以及为什么感兴趣的人使用:

这是对 chef 工作方式的副作用,这是第一次编译资源以构建集合,在此阶段,食谱中的任何 ruby 代码(ruby_block 资源之外)如果评估。一旦完成,资源收集就会收敛(将期望状态与实际状态进行比较,并完成相关操作)。

以下食谱可以:

package "zsh" do
  action :install
end

user "myuser" do
  action :create
  shell lazy { File.exists? "/bin/zsh" ? "/bin/zsh" : "/bin/bash" }
end

这里发生的是 shell 属性值的计算延迟到收敛阶段,我们必须使用 if-then-else 构造(这里使用三元运算符,因为我发现它更多可读)回退到 shell 我们确定会存在(我使用 /bin/bash,但故障安全值将是 /bin/sh)或 shell 属性将为零, 这是不允许的。

通过这种延迟评估,“/bin/zsh”是否存在的测试是在安装包并且文件应该存在之后完成的。如果包中出现问题,用户资源仍将创建用户,但使用“/bin/bash”