the resource_directory
has only 2 actions available: create
and delete
I need to update the owner and group of a directory recursi
I would use plain resource directory with action :create
.
Per documentation:
:create
Default. Create a directory. If a directory already exists (but does not match), update that directory to match
https://docs.chef.io/resource_directory.html
We could write a chef resource which iterates through your directory hierarchy and creates a file or directory resource for every file that it finds and then set it up to manage the owner and group on those files. You won't like that, however, since if you have a thousand files in that directory then you'll get a thousand chef resources and your converges will be slow.
If you want to you can, in fact, roll your own code which does something like that which I wrote in the ticket tickets.opscode.com/browse/CHEF-690 which @name referenced, but I wouldn't recommend it.
If you're trying to prevent "tampering" and fix random corruption of user and group attributes then your solution is probably correct. You'll always execute that command on every chef convergence and the resource will always show as being updated, but the command will run as fast as possible (chown -R is basically convergent and idempotent as it checks the perms before trying to set the perms). You will not get reporting back on fixed perms which is the only downside.
If you are just trying to fix the perms once on building a server, then you should throw a not_if conditional in there to check that if the root directory has the correct perms you don't run it every time. That will give you idempotent behavior and will not execute the command on every run, but the downside is clearly that if one of the files under that directory structure has its perms mangled by someone or something in the future, then it will not get corrected.
There's a possible use case here for a single resource which behaves like chown -R and then reports what it fixed (and array of files that had perms changed) which would be useful for cases like SOX and PCI-DSS reporting, but we don't currently cover that use case.
tl;dr is that your solution is fine and you can add a not_if guard if you like
You can set the default action to nothing then have resources that may screw things up notify the perm fixer:
execute "chown-data-www" do
command "chown -R www-data:www-data /var/www/myfoler"
user "root"
action :nothing
end
resource "that may screw up perms" do
stuff "one two three"
notifies :run, execute "chown-data-www"
end
with more options you could have the action :run but not if the parent folder is already the correct perms. You could alter this to include a deeper/problem file/directory, or with a find command similar to this
execute "chown-data-www" do
command "chown -R www-data:www-data /var/www/myfoler"
user "root"
action :run
not_if '[ $(stat -c %U /var/www/myfolder) = "www-data" ]'
end
Edit: fix to reflect comment below
If this as a one-off to fix permissions your shortest path might be just knife ssh. (I just did that after ending up here on my own search.)
knife ssh 'name:*' "sudo chown -R $user:$group /full/path/to/directory"
knife ssh 'name:*' "sudo chmod -R 770 /full/path/to/directory"
If I were setting this up from scratch I think I'd need to set up the directory path and proper permissions with one line (NOTE: explicitly apply the perms to each parent in the path)
%w[ /foo /foo/bar /foo/bar/baz ].each do |path|
directory path do
owner 'root'
group 'root'
mode '0755'
end
and then create each individual file as a cookbook_file.
https://stackoverflow.com/a/28283020/11822923
Answer met my need but there is an issue with grep
command, even if the user is apache2
or apach
the grep exit code will be 0
, but I needed the user to exactly be apache
(Apache web server user on CentOS 7.7).
Here is my recipe:
node["apache"]["sites"].each do |sitename, data|
document_root = "/content/sites/#{sitename}"
directory document_root do
action :create
mode "0755"
recursive true
owner "apache"
group "apache"
end
execute "chown_to_apache_user" do
command "chown -R apache:apache /content"
user "root"
action :run
not_if '[ $(stat -c %U /content/) = "apache" ]'
end
template "/etc/httpd/conf.d/#{sitename}.conf" do
source "vhost.erb"
mode "0644"
variables(
:document_root => document_root,
:port => data["port"],
:domain => data["domain"]
)
notifies :restart, "service[httpd]"
end
end
For comparison:
P.S.: to check group
as well:
node["apache"]["sites"].each do |sitename, data|
document_root = "/content/sites/#{sitename}"
directory document_root do
action :create
mode "0755"
recursive true
owner "apache"
group "apache"
end
execute "chown_to_apache_user" do
command "chown -R apache:apache /content"
user "root"
action :run
not_if '[ $(stat -c %U /content/) = "apache" ] && [ $(stat -c %G /content/) = "apache" ]'
end
template "/etc/httpd/conf.d/#{sitename}.conf" do
source "vhost.erb"
mode "0644"
variables(
:document_root => document_root,
:port => data["port"],
:domain => data["domain"]
)
notifies :restart, "service[httpd]"
end
end