Home > Back-end >  chef guard only_if with '&&' not adhering to both statements
chef guard only_if with '&&' not adhering to both statements

Time:02-23

I have the below hash in a chef recipe, that creates a directory/s

node['fnb_base_directory']['directory_name'].map do |directory_name, dir|
  next if directory_name.empty?
  directory directory_name do
    owner     dir['owner']
    group     dir['group']
    mode      dir['mode']
    recursive dir['recursive']
    action    dir['action']
    only_if "getent passwd #{dir['owner']}" && "getent group #{dir['group']}"
  end
end

I ONLY want chef to try create the directory based on this guard:

only_if "getent passwd #{dir['owner']}" && "getent group #{dir['group']}"

So that basically means that BOTH the user and the group must exist before trying to create the directory.

The problem appears to be that when chef interprets this, I see it is only adhering to ONE of the statements i.e. ONLY checks that group exists and then proceeds to attempt to create the directory, but will fail because the user does not exist yet. See below interpretation:

directory("/opt/test_dir_creation") do
  action [:create]
  default_guard_interpreter :default
  declared_type :directory
  cookbook_name "fnb_base_wrapper"
  recipe_name "fnb_base_directory"
  recursive false
  owner "nonexistent_user"
  group "opc"
  mode "0755"
  only_if "getent group opc"
end

Failure:

directory[/opt/test_dir_creation] action create
* cannot determine user id for 'nonexistent_user', does the user exist on this system?
================================================================================
Error executing action `create` on resource 'directory[/opt/test_dir_creation]'
================================================================================

Chef::Exceptions::UserIDNotFound
--------------------------------
cannot determine user id for 'nonexistent_user', does the user exist on this system?

The reason the user does not exist yet, is because that user is created in another cookbook whose priority is not as high as our base cook (which creates directories), hence why the directory creation is done before the user is created.

The directory will then be created on the 2nd converge, where the user will then exist, and proceed to create the directory ONLY then.

FYI. I am using getent because we use AD on our servers, so it may not always be a static user/group, but one that resides in AD.

I have also checked this question: Using multiple conditions in Chef only_if guard

It does not help me.

Your help, guidance and advice will be greatly appreciated.

CodePudding user response:

Try removing the quotes in the middle so the whole expression including the && condition runs in the shell.

only_if "getent passwd #{dir['owner']} && getent group #{dir['group']}"

Chef accepts a string shell command or a ruby block

only_if "some shell commands which are possibly in a pipeline return 0"

only_if {
  return true if <condition1> && <condition2>
  return true if <condition3> || <condition4>
  return false
}
  • Related