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
}