# Dynamically modifying files from a package Chef just installed

**URL:** <https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557>\
**Category:** Chef Infra (archive)\
**Created:** [October 11, 2013, 3:12pm UTC](https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557 "2013-10-11T15:12:16Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rob\_Curtis](https://avatars.discourse-cdn.com/v4/letter/r/bbce88/32.png) [@Rob\_Curtis](https://discourse.chef.io/u/Rob_Curtis)\
**Post date:** [October 11, 2013, 3:12pm UTC](https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557/1 "2013-10-11T15:12:16Z")

</div>

Executive Summary:  
I’m using Chef to install a package and then update (ownership, permissions)  
many of the files installed with the package. Because the files don’t exist  
before the package is installed in the execution phase, resources for those  
files can’t be dynamically generated in the compile phase. What is the most  
correct (idempotent, efficient) way to update the package’s files after  
install? Do I just use a Ruby block to chown/chmod the files? Do I create an  
explicit resource for each and every file?

The longer version:  
We are using Chef to install and configure a particular software bundle (Mule  
ESB). In keeping with what we understand to be the best practices, we have a  
library cookbook that simply does the bare-bones install and a policy cookbook  
that wraps the library cookbook and performs our own customization.

Most of the customization we want to perform is modifying the ownership and  
permissions on many of the files that get installed by the library cookbook to  
make our security guys happy. My first cut at the default recipe in the policy  
cookbook looks something like this:

### Do things that happen before installing Mule

Chef::Log.debug(“Pre-Mule”)

### Install Mule

include\_recipe “mule”

### Do things that happen after installing Mule

Chef::Log.debug(“Post-Mule”)

# Remove example applications

directory “#{node[:mule][:home]}/examples” do  
recursive true  
action :delete  
end

# Restrict access to config files

Dir[“#{node[:mule][:home]}/conf/\*” ].each do |path|  
file path do  
owner node[:mule-policy][:user]  
group node[:mule-policy][:group]  
mode "0640"  
end if File.file?(path)  
end

### End of cookbook snippet

The problem is that when I run the mule-policy cookbook on a fresh VM, Chef  
attempts to create the config file resources during the compile phase but since  
Mule doesn’t actually get installed until the execution phase, there are no  
config files for which to generate resources. It’s not a huge deal with the  
config files since there are only 3 of them, but it’s a bigger problem when we  
start getting into the /lib directory, which contains dozens of .jar files and  
the security guys want those locked down, too.

Any advice would be greatly appreciated.

Thanks,

-Rob

---

<div class="post-metadata">

**Author:** ![Andrew\_Gross](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/andrew_gross/32/320_2.png) [@Andrew\_Gross](https://discourse.chef.io/u/Andrew_Gross)\
**Post date:** [October 11, 2013, 3:19pm UTC](https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557/2 "2013-10-11T15:19:25Z")

</div>

Hey Rob,

The normal pattern for this sort of thing is to have the post install  
modification use 'action :nothing' and then send them a notification from  
the package install to kick off a chain of events. Something similar to  
this:

package "foo" do  
version "bar"  
action :install  
notifies :create, "file[/etc/foo/bar]", :immediately  
end

file "/etc/foo/bar" do  
mode 00644  
action :nothing  
end

On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:

> Executive Summary:  
> I'm using Chef to install a package and then update (ownership,  
> permissions)  
> many of the files installed with the package. Because the files don't  
> exist  
> before the package is installed in the execution phase, resources for those  
> files can't be dynamically generated in the compile phase. What is the  
> most  
> correct (idempotent, efficient) way to update the package's files after  
> install? Do I just use a Ruby block to chown/chmod the files? Do I  
> create an  
> explicit resource for each and every file?
> 
> The longer version:  
> We are using Chef to install and configure a particular software bundle  
> (Mule  
> ESB). In keeping with what we understand to be the best practices, we  
> have a  
> library cookbook that simply does the bare-bones install and a policy  
> cookbook  
> that wraps the library cookbook and performs our own customization.
> 
> Most of the customization we want to perform is modifying the ownership and  
> permissions on many of the files that get installed by the library  
> cookbook to  
> make our security guys happy. My first cut at the default recipe in the  
> policy  
> cookbook looks something like this:
> 
> ### Do things that happen before installing Mule
> 
> Chef::Log.debug("Pre-Mule")
> 
> ### Install Mule
> 
> include\_recipe "mule"
> 
> ### Do things that happen after installing Mule
> 
> Chef::Log.debug("Post-Mule")
> 
> # Remove example applications
> 
> directory "#{node[:mule][:home]}/examples" do  
> recursive true  
> action :delete  
> end
> 
> # Restrict access to config files
> 
> Dir["#{node[:mule][:home]}/conf/\*" ].each do |path|  
> file path do  
> owner node[:mule-policy][:user]  
> group node[:mule-policy][:group]  
> mode "0640"  
> end if File.file?(path)  
> end
> 
> ### End of cookbook snippet
> 
> The problem is that when I run the mule-policy cookbook on a fresh VM, Chef  
> attempts to create the config file resources during the compile phase but  
> since  
> Mule doesn't actually get installed until the execution phase, there are no  
> config files for which to generate resources. It's not a huge deal with  
> the  
> config files since there are only 3 of them, but it's a bigger problem  
> when we  
> start getting into the /lib directory, which contains dozens of .jar files  
> and  
> the security guys want those locked down, too.
> 
> Any advice would be greatly appreciated.
> 
> Thanks,
> 
> -Rob

---

<div class="post-metadata">

**Author:** ![Rob\_Curtis](https://avatars.discourse-cdn.com/v4/letter/r/bbce88/32.png) [@Rob\_Curtis](https://discourse.chef.io/u/Rob_Curtis)\
**Post date:** [October 11, 2013, 3:49pm UTC](https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557/3 "2013-10-11T15:49:23Z")

</div>

Andrew,

First, thanks for the quick response. It's always a bit nerve-wracking  
submitting your first question to a new mailing list.

It seems like if I go down that road, I'll end up having to explicitly  
define a file or directory resource for everything in the package, which  
would leave me with a huge policy cookbook that may need a major overhaul  
when we upgrade to a newer version of the COTS package.

I was really hoping to do things a little more dynamically, but simply  
writing a Ruby block that walks the tree of subdirectories and files at  
execution time changing ownership and permission seems less "correct" than  
using file and directory resources.

Chef isn't psychic, so I have to believe that my attempt to dynamically  
create file and directory resources during the compile phase for stuff that  
won't exist until the execution phase is just doomed to fail.

The more I think about it, the more I think I'm just going to have to write  
some execution phase code to walk through the file system and make the  
necessary ownership and permission changes on the installed files and  
directories.

On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross [andrew@yipit.com](mailto:andrew@yipit.com) wrote:

> Hey Rob,
> 
> The normal pattern for this sort of thing is to have the post install  
> modification use 'action :nothing' and then send them a notification from  
> the package install to kick off a chain of events. Something similar to  
> this:
> 
> package "foo" do  
> version "bar"  
> action :install  
> notifies :create, "file[/etc/foo/bar]", :immediately  
> end
> 
> file "/etc/foo/bar" do  
> mode 00644  
> action :nothing  
> end
> 
> On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:
> 
> > Executive Summary:  
> > I'm using Chef to install a package and then update (ownership,  
> > permissions)  
> > many of the files installed with the package. Because the files don't  
> > exist  
> > before the package is installed in the execution phase, resources for  
> > those  
> > files can't be dynamically generated in the compile phase. What is the  
> > most  
> > correct (idempotent, efficient) way to update the package's files after  
> > install? Do I just use a Ruby block to chown/chmod the files? Do I  
> > create an  
> > explicit resource for each and every file?
> > 
> > The longer version:  
> > We are using Chef to install and configure a particular software bundle  
> > (Mule  
> > ESB). In keeping with what we understand to be the best practices, we  
> > have a  
> > library cookbook that simply does the bare-bones install and a policy  
> > cookbook  
> > that wraps the library cookbook and performs our own customization.
> > 
> > Most of the customization we want to perform is modifying the ownership  
> > and  
> > permissions on many of the files that get installed by the library  
> > cookbook to  
> > make our security guys happy. My first cut at the default recipe in the  
> > policy  
> > cookbook looks something like this:
> > 
> > ### Do things that happen before installing Mule
> > 
> > Chef::Log.debug("Pre-Mule")
> > 
> > ### Install Mule
> > 
> > include\_recipe "mule"
> > 
> > ### Do things that happen after installing Mule
> > 
> > Chef::Log.debug("Post-Mule")
> > 
> > # Remove example applications
> > 
> > directory "#{node[:mule][:home]}/examples" do  
> > recursive true  
> > action :delete  
> > end
> > 
> > # Restrict access to config files
> > 
> > Dir["#{node[:mule][:home]}/conf/\*" ].each do |path|  
> > file path do  
> > owner node[:mule-policy][:user]  
> > group node[:mule-policy][:group]  
> > mode "0640"  
> > end if File.file?(path)  
> > end
> > 
> > ### End of cookbook snippet
> > 
> > The problem is that when I run the mule-policy cookbook on a fresh VM,  
> > Chef  
> > attempts to create the config file resources during the compile phase but  
> > since  
> > Mule doesn't actually get installed until the execution phase, there are  
> > no  
> > config files for which to generate resources. It's not a huge deal with  
> > the  
> > config files since there are only 3 of them, but it's a bigger problem  
> > when we  
> > start getting into the /lib directory, which contains dozens of .jar  
> > files and  
> > the security guys want those locked down, too.
> > 
> > Any advice would be greatly appreciated.
> > 
> > Thanks,
> > 
> > -Rob

---

<div class="post-metadata">

**Author:** ![Andrew\_Gross](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/andrew_gross/32/320_2.png) [@Andrew\_Gross](https://discourse.chef.io/u/Andrew_Gross)\
**Post date:** [October 11, 2013, 5:25pm UTC](https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557/4 "2013-10-11T17:25:13Z")

</div>

Some additional options instead of using `file`, just change the  
notification.

execute "Set Permissions" do  
command "chmod -R 644 /etc/foo/bar  
action :nothing  
only\_if { ::File.exists?("/etc/foo/bar/baz.conf")}  
end

We can also outsource the directory spidering to Ruby (

> <https://stackoverflow.com/questions/2370702/one-liner-to-recursively-list-directories-in-ruby>

)

# Set files

Dir.glob("/etc/foo/\*\*/\*").each do |f|  
file "Set permissions for #{f}" do  
mode 00644  
action :create  
end if ::File.exists?("/etc/foo")

# Set Directories

Dir.glob("/etc/foo/\*\*/\*/").each do |d|  
directory "Set permissions for #{d}" do  
mode 00755  
action :create  
end if ::File.exists?("/etc/foo")

On Fri, Oct 11, 2013 at 11:49 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:

> Andrew,
> 
> First, thanks for the quick response. It's always a bit nerve-wracking  
> submitting your first question to a new mailing list.
> 
> It seems like if I go down that road, I'll end up having to explicitly  
> define a file or directory resource for everything in the package, which  
> would leave me with a huge policy cookbook that may need a major overhaul  
> when we upgrade to a newer version of the COTS package.
> 
> I was really hoping to do things a little more dynamically, but simply  
> writing a Ruby block that walks the tree of subdirectories and files at  
> execution time changing ownership and permission seems less "correct" than  
> using file and directory resources.
> 
> Chef isn't psychic, so I have to believe that my attempt to dynamically  
> create file and directory resources during the compile phase for stuff that  
> won't exist until the execution phase is just doomed to fail.
> 
> The more I think about it, the more I think I'm just going to have to  
> write some execution phase code to walk through the file system and make  
> the necessary ownership and permission changes on the installed files and  
> directories.
> 
> On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross [andrew@yipit.com](mailto:andrew@yipit.com) wrote:
> 
> > Hey Rob,
> > 
> > The normal pattern for this sort of thing is to have the post install  
> > modification use 'action :nothing' and then send them a notification from  
> > the package install to kick off a chain of events. Something similar to  
> > this:
> > 
> > package "foo" do  
> > version "bar"  
> > action :install  
> > notifies :create, "file[/etc/foo/bar]", :immediately  
> > end
> > 
> > file "/etc/foo/bar" do  
> > mode 00644  
> > action :nothing  
> > end
> > 
> > On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:
> > 
> > > Executive Summary:  
> > > I'm using Chef to install a package and then update (ownership,  
> > > permissions)  
> > > many of the files installed with the package. Because the files don't  
> > > exist  
> > > before the package is installed in the execution phase, resources for  
> > > those  
> > > files can't be dynamically generated in the compile phase. What is the  
> > > most  
> > > correct (idempotent, efficient) way to update the package's files after  
> > > install? Do I just use a Ruby block to chown/chmod the files? Do I  
> > > create an  
> > > explicit resource for each and every file?
> > > 
> > > The longer version:  
> > > We are using Chef to install and configure a particular software bundle  
> > > (Mule  
> > > ESB). In keeping with what we understand to be the best practices, we  
> > > have a  
> > > library cookbook that simply does the bare-bones install and a policy  
> > > cookbook  
> > > that wraps the library cookbook and performs our own customization.
> > > 
> > > Most of the customization we want to perform is modifying the ownership  
> > > and  
> > > permissions on many of the files that get installed by the library  
> > > cookbook to  
> > > make our security guys happy. My first cut at the default recipe in the  
> > > policy  
> > > cookbook looks something like this:
> > > 
> > > ### Do things that happen before installing Mule
> > > 
> > > Chef::Log.debug("Pre-Mule")
> > > 
> > > ### Install Mule
> > > 
> > > include\_recipe "mule"
> > > 
> > > ### Do things that happen after installing Mule
> > > 
> > > Chef::Log.debug("Post-Mule")
> > > 
> > > # Remove example applications
> > > 
> > > directory "#{node[:mule][:home]}/examples" do  
> > > recursive true  
> > > action :delete  
> > > end
> > > 
> > > # Restrict access to config files
> > > 
> > > Dir["#{node[:mule][:home]}/conf/\*" ].each do |path|  
> > > file path do  
> > > owner node[:mule-policy][:user]  
> > > group node[:mule-policy][:group]  
> > > mode "0640"  
> > > end if File.file?(path)  
> > > end
> > > 
> > > ### End of cookbook snippet
> > > 
> > > The problem is that when I run the mule-policy cookbook on a fresh VM,  
> > > Chef  
> > > attempts to create the config file resources during the compile phase  
> > > but since  
> > > Mule doesn't actually get installed until the execution phase, there are  
> > > no  
> > > config files for which to generate resources. It's not a huge deal with  
> > > the  
> > > config files since there are only 3 of them, but it's a bigger problem  
> > > when we  
> > > start getting into the /lib directory, which contains dozens of .jar  
> > > files and  
> > > the security guys want those locked down, too.
> > > 
> > > Any advice would be greatly appreciated.
> > > 
> > > Thanks,
> > > 
> > > -Rob

---

<div class="post-metadata">

**Author:** ![Rob\_Curtis](https://avatars.discourse-cdn.com/v4/letter/r/bbce88/32.png) [@Rob\_Curtis](https://discourse.chef.io/u/Rob_Curtis)\
**Post date:** [October 11, 2013, 7:30pm UTC](https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557/5 "2013-10-11T19:30:38Z")

</div>

So here's where I've landed. I am using ruby blocks which spider the  
directories and create new chef resource objects. I've been testing it and  
it seems to be working pretty well. Since I'm relying on Chef resources -  
even though they're dynamically generated during the execution phase - the  
cookbook is idempotent and Chef isn't executing any unnecessary actions.

The code looks something like this:

##### Begin Policy Cookbook Snippet

# Cookbook: mule-policy

# Recipe: default

# Set up a RunContext for later use

@events = Chef::EventDispatch::Dispatcher.new()  
run\_context = Chef::RunContext.new( node, {}, @events )

# Run the library cookbook

include\_recipe "mule"

# Remove example applications

directory "#{node[:mule][:home]}/examples" do  
recursive true  
action :delete  
end

# Restrict access to config files

ruby\_block "restrict\_config\_files" do  
notifies :restart, "service[mule]"  
action :create  
block do  
Dir["#{node[:mule][:home]}/conf/\*" ].each do |path|  
conf\_file = Chef::Resource::File.new( path, run\_context )  
conf\_file.owner node[:mule][:user]  
conf\_file.group node[:mule][:group]  
conf\_file.mode "0640"  
conf\_file.run\_action :create  
end  
end  
end

# Restrict access to library files

# This was the gnarly bit due to the number of .jar files

ruby\_block "restrict\_library\_files" do  
notifies :restart, "service[mule]"  
action :create  
block do  
Dir["#{node[:mule][:home]}/lib/\*\*/\*" ].each do |path|  
if File.file?( path )  
lib\_file = Chef::Resource::File.new( path, run\_context )  
lib\_file.owner node[:mule][:user]  
lib\_file.group node[:mule][:group]  
lib\_file.mode "0640"  
lib\_file.run\_action :create  
elsif File.directory?( path )  
lib\_dir= Chef::Resource::Directory.new( path, run\_context )  
lib\_dir.owner node[:mule][:user]  
lib\_dir.group node[:mule][:group]  
lib\_dir.mode "0750"  
lib\_dir.run\_action :create  
end  
end  
end  
end

##### End Policy Cookbook Snippet

I'm pretty happy with it. If anyone has any further comments or  
suggestions, I'd be glad to hear them.

Thanks,

-Rob

On Fri, Oct 11, 2013 at 12:25 PM, Andrew Gross [andrew@yipit.com](mailto:andrew@yipit.com) wrote:

> Some additional options instead of using `file`, just change the  
> notification.
> 
> execute "Set Permissions" do  
> command "chmod -R 644 /etc/foo/bar  
> action :nothing  
> only\_if { ::File.exists?("/etc/foo/bar/baz.conf")}  
> end
> 
> We can also outsource the directory spidering to Ruby (  
> [filesystems - One-liner to recursively list directories in Ruby? - Stack Overflow](http://stackoverflow.com/questions/2370702/one-liner-to-recursively-list-directories-in-ruby)  
> )
> 
> # Set files
> 
> Dir.glob("/etc/foo/\*\*/\*").each do |f|  
> file "Set permissions for #{f}" do  
> mode 00644  
> action :create  
> end if ::File.exists?("/etc/foo")
> 
> # Set Directories
> 
> Dir.glob("/etc/foo/\*\*/\*/").each do |d|  
> directory "Set permissions for #{d}" do  
> mode 00755  
> action :create  
> end if ::File.exists?("/etc/foo")
> 
> On Fri, Oct 11, 2013 at 11:49 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:
> 
> > Andrew,
> > 
> > First, thanks for the quick response. It's always a bit nerve-wracking  
> > submitting your first question to a new mailing list.
> > 
> > It seems like if I go down that road, I'll end up having to explicitly  
> > define a file or directory resource for everything in the package, which  
> > would leave me with a huge policy cookbook that may need a major overhaul  
> > when we upgrade to a newer version of the COTS package.
> > 
> > I was really hoping to do things a little more dynamically, but simply  
> > writing a Ruby block that walks the tree of subdirectories and files at  
> > execution time changing ownership and permission seems less "correct" than  
> > using file and directory resources.
> > 
> > Chef isn't psychic, so I have to believe that my attempt to dynamically  
> > create file and directory resources during the compile phase for stuff that  
> > won't exist until the execution phase is just doomed to fail.
> > 
> > The more I think about it, the more I think I'm just going to have to  
> > write some execution phase code to walk through the file system and make  
> > the necessary ownership and permission changes on the installed files and  
> > directories.
> > 
> > On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross [andrew@yipit.com](mailto:andrew@yipit.com) wrote:
> > 
> > > Hey Rob,
> > > 
> > > The normal pattern for this sort of thing is to have the post install  
> > > modification use 'action :nothing' and then send them a notification from  
> > > the package install to kick off a chain of events. Something similar to  
> > > this:
> > > 
> > > package "foo" do  
> > > version "bar"  
> > > action :install  
> > > notifies :create, "file[/etc/foo/bar]", :immediately  
> > > end
> > > 
> > > file "/etc/foo/bar" do  
> > > mode 00644  
> > > action :nothing  
> > > end
> > > 
> > > On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:
> > > 
> > > > Executive Summary:  
> > > > I'm using Chef to install a package and then update (ownership,  
> > > > permissions)  
> > > > many of the files installed with the package. Because the files don't  
> > > > exist  
> > > > before the package is installed in the execution phase, resources for  
> > > > those  
> > > > files can't be dynamically generated in the compile phase. What is the  
> > > > most  
> > > > correct (idempotent, efficient) way to update the package's files after  
> > > > install? Do I just use a Ruby block to chown/chmod the files? Do I  
> > > > create an  
> > > > explicit resource for each and every file?
> > > > 
> > > > The longer version:  
> > > > We are using Chef to install and configure a particular software bundle  
> > > > (Mule  
> > > > ESB). In keeping with what we understand to be the best practices, we  
> > > > have a  
> > > > library cookbook that simply does the bare-bones install and a policy  
> > > > cookbook  
> > > > that wraps the library cookbook and performs our own customization.
> > > > 
> > > > Most of the customization we want to perform is modifying the ownership  
> > > > and  
> > > > permissions on many of the files that get installed by the library  
> > > > cookbook to  
> > > > make our security guys happy. My first cut at the default recipe in  
> > > > the policy  
> > > > cookbook looks something like this:
> > > > 
> > > > ### Do things that happen before installing Mule
> > > > 
> > > > Chef::Log.debug("Pre-Mule")
> > > > 
> > > > ### Install Mule
> > > > 
> > > > include\_recipe "mule"
> > > > 
> > > > ### Do things that happen after installing Mule
> > > > 
> > > > Chef::Log.debug("Post-Mule")
> > > > 
> > > > # Remove example applications
> > > > 
> > > > directory "#{node[:mule][:home]}/examples" do  
> > > > recursive true  
> > > > action :delete  
> > > > end
> > > > 
> > > > # Restrict access to config files
> > > > 
> > > > Dir["#{node[:mule][:home]}/conf/\*" ].each do |path|  
> > > > file path do  
> > > > owner node[:mule-policy][:user]  
> > > > group node[:mule-policy][:group]  
> > > > mode "0640"  
> > > > end if File.file?(path)  
> > > > end
> > > > 
> > > > ### End of cookbook snippet
> > > > 
> > > > The problem is that when I run the mule-policy cookbook on a fresh VM,  
> > > > Chef  
> > > > attempts to create the config file resources during the compile phase  
> > > > but since  
> > > > Mule doesn't actually get installed until the execution phase, there  
> > > > are no  
> > > > config files for which to generate resources. It's not a huge deal  
> > > > with the  
> > > > config files since there are only 3 of them, but it's a bigger problem  
> > > > when we  
> > > > start getting into the /lib directory, which contains dozens of .jar  
> > > > files and  
> > > > the security guys want those locked down, too.
> > > > 
> > > > Any advice would be greatly appreciated.
> > > > 
> > > > Thanks,
> > > > 
> > > > -Rob

---

<div class="post-metadata">

**Author:** ![steve](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/steve/32/294_2.png) [@steve](https://discourse.chef.io/u/steve)\
**Post date:** [October 11, 2013, 7:52pm UTC](https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557/6 "2013-10-11T19:52:46Z")

</div>

The difference between your excerpt and Rob's is that his is wrapped in a  
ruby\_block resource. Your code will be evaluated (and, therefore, the  
directory will be walked) during the compile phase ... for Rob's particular  
scenario, he wants the directory walk (and resource creation) to take place  
_after_ the package is present.

So if he did things your way, it would take two Chef runs to obtain the  
desired end state.

I have the feeling everyone on this thread already knew this, but I thought  
I'd clarify this for the sake of posterity (i.e. whoever finds this example  
via search engine).

On Fri, Oct 11, 2013 at 10:25 AM, Andrew Gross [andrew@yipit.com](mailto:andrew@yipit.com) wrote:

> Some additional options instead of using `file`, just change the  
> notification.
> 
> execute "Set Permissions" do  
> command "chmod -R 644 /etc/foo/bar  
> action :nothing  
> only\_if { ::File.exists?("/etc/foo/bar/baz.conf")}  
> end
> 
> We can also outsource the directory spidering to Ruby (  
> [filesystems - One-liner to recursively list directories in Ruby? - Stack Overflow](http://stackoverflow.com/questions/2370702/one-liner-to-recursively-list-directories-in-ruby)  
> )
> 
> # Set files
> 
> Dir.glob("/etc/foo/\*\*/\*").each do |f|  
> file "Set permissions for #{f}" do  
> mode 00644  
> action :create  
> end if ::File.exists?("/etc/foo")
> 
> # Set Directories
> 
> Dir.glob("/etc/foo/\*\*/\*/").each do |d|  
> directory "Set permissions for #{d}" do  
> mode 00755  
> action :create  
> end if ::File.exists?("/etc/foo")
> 
> On Fri, Oct 11, 2013 at 11:49 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:
> 
> > Andrew,
> > 
> > First, thanks for the quick response. It's always a bit nerve-wracking  
> > submitting your first question to a new mailing list.
> > 
> > It seems like if I go down that road, I'll end up having to explicitly  
> > define a file or directory resource for everything in the package, which  
> > would leave me with a huge policy cookbook that may need a major overhaul  
> > when we upgrade to a newer version of the COTS package.
> > 
> > I was really hoping to do things a little more dynamically, but simply  
> > writing a Ruby block that walks the tree of subdirectories and files at  
> > execution time changing ownership and permission seems less "correct" than  
> > using file and directory resources.
> > 
> > Chef isn't psychic, so I have to believe that my attempt to dynamically  
> > create file and directory resources during the compile phase for stuff that  
> > won't exist until the execution phase is just doomed to fail.
> > 
> > The more I think about it, the more I think I'm just going to have to  
> > write some execution phase code to walk through the file system and make  
> > the necessary ownership and permission changes on the installed files and  
> > directories.
> > 
> > On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross [andrew@yipit.com](mailto:andrew@yipit.com) wrote:
> > 
> > > Hey Rob,
> > > 
> > > The normal pattern for this sort of thing is to have the post install  
> > > modification use 'action :nothing' and then send them a notification from  
> > > the package install to kick off a chain of events. Something similar to  
> > > this:
> > > 
> > > package "foo" do  
> > > version "bar"  
> > > action :install  
> > > notifies :create, "file[/etc/foo/bar]", :immediately  
> > > end
> > > 
> > > file "/etc/foo/bar" do  
> > > mode 00644  
> > > action :nothing  
> > > end
> > > 
> > > On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:
> > > 
> > > > Executive Summary:  
> > > > I'm using Chef to install a package and then update (ownership,  
> > > > permissions)  
> > > > many of the files installed with the package. Because the files don't  
> > > > exist  
> > > > before the package is installed in the execution phase, resources for  
> > > > those  
> > > > files can't be dynamically generated in the compile phase. What is the  
> > > > most  
> > > > correct (idempotent, efficient) way to update the package's files after  
> > > > install? Do I just use a Ruby block to chown/chmod the files? Do I  
> > > > create an  
> > > > explicit resource for each and every file?
> > > > 
> > > > The longer version:  
> > > > We are using Chef to install and configure a particular software bundle  
> > > > (Mule  
> > > > ESB). In keeping with what we understand to be the best practices, we  
> > > > have a  
> > > > library cookbook that simply does the bare-bones install and a policy  
> > > > cookbook  
> > > > that wraps the library cookbook and performs our own customization.
> > > > 
> > > > Most of the customization we want to perform is modifying the ownership  
> > > > and  
> > > > permissions on many of the files that get installed by the library  
> > > > cookbook to  
> > > > make our security guys happy. My first cut at the default recipe in  
> > > > the policy  
> > > > cookbook looks something like this:
> > > > 
> > > > ### Do things that happen before installing Mule
> > > > 
> > > > Chef::Log.debug("Pre-Mule")
> > > > 
> > > > ### Install Mule
> > > > 
> > > > include\_recipe "mule"
> > > > 
> > > > ### Do things that happen after installing Mule
> > > > 
> > > > Chef::Log.debug("Post-Mule")
> > > > 
> > > > # Remove example applications
> > > > 
> > > > directory "#{node[:mule][:home]}/examples" do  
> > > > recursive true  
> > > > action :delete  
> > > > end
> > > > 
> > > > # Restrict access to config files
> > > > 
> > > > Dir["#{node[:mule][:home]}/conf/\*" ].each do |path|  
> > > > file path do  
> > > > owner node[:mule-policy][:user]  
> > > > group node[:mule-policy][:group]  
> > > > mode "0640"  
> > > > end if File.file?(path)  
> > > > end
> > > > 
> > > > ### End of cookbook snippet
> > > > 
> > > > The problem is that when I run the mule-policy cookbook on a fresh VM,  
> > > > Chef  
> > > > attempts to create the config file resources during the compile phase  
> > > > but since  
> > > > Mule doesn't actually get installed until the execution phase, there  
> > > > are no  
> > > > config files for which to generate resources. It's not a huge deal  
> > > > with the  
> > > > config files since there are only 3 of them, but it's a bigger problem  
> > > > when we  
> > > > start getting into the /lib directory, which contains dozens of .jar  
> > > > files and  
> > > > the security guys want those locked down, too.
> > > > 
> > > > Any advice would be greatly appreciated.
> > > > 
> > > > Thanks,
> > > > 
> > > > -Rob

---

<div class="post-metadata">

**Author:** ![Andrew\_Gross](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/andrew_gross/32/320_2.png) [@Andrew\_Gross](https://discourse.chef.io/u/Andrew_Gross)\
**Post date:** [October 11, 2013, 9:16pm UTC](https://discourse.chef.io/t/dynamically-modifying-files-from-a-package-chef-just-installed/4557/7 "2013-10-11T21:16:06Z")

</div>

Completely forgot about to embed in a ruby\_block, definitely a better way  
to do it.

On Fri, Oct 11, 2013 at 3:52 PM, steve . [leftathome@gmail.com](mailto:leftathome@gmail.com) wrote:

> The difference between your excerpt and Rob's is that his is wrapped in a  
> ruby\_block resource. Your code will be evaluated (and, therefore, the  
> directory will be walked) during the compile phase ... for Rob's particular  
> scenario, he wants the directory walk (and resource creation) to take place  
> _after_ the package is present.
> 
> So if he did things your way, it would take two Chef runs to obtain the  
> desired end state.
> 
> I have the feeling everyone on this thread already knew this, but I  
> thought I'd clarify this for the sake of posterity (i.e. whoever finds this  
> example via search engine).
> 
> On Fri, Oct 11, 2013 at 10:25 AM, Andrew Gross [andrew@yipit.com](mailto:andrew@yipit.com) wrote:
> 
> > Some additional options instead of using `file`, just change the  
> > notification.
> > 
> > execute "Set Permissions" do  
> > command "chmod -R 644 /etc/foo/bar  
> > action :nothing  
> > only\_if { ::File.exists?("/etc/foo/bar/baz.conf")}  
> > end
> > 
> > We can also outsource the directory spidering to Ruby (  
> > [filesystems - One-liner to recursively list directories in Ruby? - Stack Overflow](http://stackoverflow.com/questions/2370702/one-liner-to-recursively-list-directories-in-ruby)  
> > )
> > 
> > # Set files
> > 
> > Dir.glob("/etc/foo/\*\*/\*").each do |f|  
> > file "Set permissions for #{f}" do  
> > mode 00644  
> > action :create  
> > end if ::File.exists?("/etc/foo")
> > 
> > # Set Directories
> > 
> > Dir.glob("/etc/foo/\*\*/\*/").each do |d|  
> > directory "Set permissions for #{d}" do  
> > mode 00755  
> > action :create  
> > end if ::File.exists?("/etc/foo")
> > 
> > On Fri, Oct 11, 2013 at 11:49 AM, Rob Curtis [robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)wrote:
> > 
> > > Andrew,
> > > 
> > > First, thanks for the quick response. It's always a bit nerve-wracking  
> > > submitting your first question to a new mailing list.
> > > 
> > > It seems like if I go down that road, I'll end up having to explicitly  
> > > define a file or directory resource for everything in the package, which  
> > > would leave me with a huge policy cookbook that may need a major overhaul  
> > > when we upgrade to a newer version of the COTS package.
> > > 
> > > I was really hoping to do things a little more dynamically, but simply  
> > > writing a Ruby block that walks the tree of subdirectories and files at  
> > > execution time changing ownership and permission seems less "correct" than  
> > > using file and directory resources.
> > > 
> > > Chef isn't psychic, so I have to believe that my attempt to dynamically  
> > > create file and directory resources during the compile phase for stuff that  
> > > won't exist until the execution phase is just doomed to fail.
> > > 
> > > The more I think about it, the more I think I'm just going to have to  
> > > write some execution phase code to walk through the file system and make  
> > > the necessary ownership and permission changes on the installed files and  
> > > directories.
> > > 
> > > On Fri, Oct 11, 2013 at 10:19 AM, Andrew Gross [andrew@yipit.com](mailto:andrew@yipit.com) wrote:
> > > 
> > > > Hey Rob,
> > > > 
> > > > The normal pattern for this sort of thing is to have the post install  
> > > > modification use 'action :nothing' and then send them a notification from  
> > > > the package install to kick off a chain of events. Something similar to  
> > > > this:
> > > > 
> > > > package "foo" do  
> > > > version "bar"  
> > > > action :install  
> > > > notifies :create, "file[/etc/foo/bar]", :immediately  
> > > > end
> > > > 
> > > > file "/etc/foo/bar" do  
> > > > mode 00644  
> > > > action :nothing  
> > > > end
> > > > 
> > > > On Fri, Oct 11, 2013 at 11:12 AM, Rob Curtis \<[robert.h.curtis@gmail.com](mailto:robert.h.curtis@gmail.com)
> > > > 
> > > > > wrote:
> > > > 
> > > > > Executive Summary:  
> > > > > I'm using Chef to install a package and then update (ownership,  
> > > > > permissions)  
> > > > > many of the files installed with the package. Because the files don't  
> > > > > exist  
> > > > > before the package is installed in the execution phase, resources for  
> > > > > those  
> > > > > files can't be dynamically generated in the compile phase. What is  
> > > > > the most  
> > > > > correct (idempotent, efficient) way to update the package's files after  
> > > > > install? Do I just use a Ruby block to chown/chmod the files? Do I  
> > > > > create an  
> > > > > explicit resource for each and every file?
> > > > > 
> > > > > The longer version:  
> > > > > We are using Chef to install and configure a particular software  
> > > > > bundle (Mule  
> > > > > ESB). In keeping with what we understand to be the best practices, we  
> > > > > have a  
> > > > > library cookbook that simply does the bare-bones install and a policy  
> > > > > cookbook  
> > > > > that wraps the library cookbook and performs our own customization.
> > > > > 
> > > > > Most of the customization we want to perform is modifying the  
> > > > > ownership and  
> > > > > permissions on many of the files that get installed by the library  
> > > > > cookbook to  
> > > > > make our security guys happy. My first cut at the default recipe in  
> > > > > the policy  
> > > > > cookbook looks something like this:
> > > > > 
> > > > > ### Do things that happen before installing Mule
> > > > > 
> > > > > Chef::Log.debug("Pre-Mule")
> > > > > 
> > > > > ### Install Mule
> > > > > 
> > > > > include\_recipe "mule"
> > > > > 
> > > > > ### Do things that happen after installing Mule
> > > > > 
> > > > > Chef::Log.debug("Post-Mule")
> > > > > 
> > > > > # Remove example applications
> > > > > 
> > > > > directory "#{node[:mule][:home]}/examples" do  
> > > > > recursive true  
> > > > > action :delete  
> > > > > end
> > > > > 
> > > > > # Restrict access to config files
> > > > > 
> > > > > Dir["#{node[:mule][:home]}/conf/\*" ].each do |path|  
> > > > > file path do  
> > > > > owner node[:mule-policy][:user]  
> > > > > group node[:mule-policy][:group]  
> > > > > mode "0640"  
> > > > > end if File.file?(path)  
> > > > > end
> > > > > 
> > > > > ### End of cookbook snippet
> > > > > 
> > > > > The problem is that when I run the mule-policy cookbook on a fresh VM,  
> > > > > Chef  
> > > > > attempts to create the config file resources during the compile phase  
> > > > > but since  
> > > > > Mule doesn't actually get installed until the execution phase, there  
> > > > > are no  
> > > > > config files for which to generate resources. It's not a huge deal  
> > > > > with the  
> > > > > config files since there are only 3 of them, but it's a bigger problem  
> > > > > when we  
> > > > > start getting into the /lib directory, which contains dozens of .jar  
> > > > > files and  
> > > > > the security guys want those locked down, too.
> > > > > 
> > > > > Any advice would be greatly appreciated.
> > > > > 
> > > > > Thanks,
> > > > > 
> > > > > -Rob
