Chef conditional resource argument

為{幸葍}努か 提交于 2019-12-13 01:39:20

问题


I'm creating a user via Chef. His properties are stored in data bag:

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

The recipe is:

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

The problem is that if zsh is not installed on node, I cannot login as developer. So, I want to conditionally apply argument for user resource, like:

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

How can I achieve this?


回答1:


To complement @mudasobwa's answer the proper way to do it in chef and avoid missing the shell if it's installed by another recipe or a package resource in the same recipe you have to use lazy attribute evaluation.

Long version for thoose interested on the how and why:

This is a side effect on how chef works, there's a first time compiling the resources to build a collection, at this phase any ruby code in a recipe (outside of a ruby_block resource) if evaluated. Once that is done the resources collection is converged (the desired state is compared to the actual state and relevant actions are done).

The following recipe would do:

package "zsh" do
  action :install
end

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

What hapens here is that the evaluation of the shell attribute value is delayed to the converge phase, we have to use a if-then-else construction (here with a ternary operator as I find it more readable) to fallback to a shell we're sure will be present (I used /bin/bash, but a failsafe value would be /bin/sh) or the shell attribute will be nil, which is not allowed.

With this delayed evaluation the test on the presence of "/bin/zsh" is done after the package has been installed and the file should be present. In case there was a problem within the package, the user resource will still create the user but with "/bin/bash"




回答2:


The easiest way to achieve what you want is to check for the shell existence explicitly:

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


来源:https://stackoverflow.com/questions/29922901/chef-conditional-resource-argument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!