How to move/copy files locally with Chef

I haven't yet come across a Chef resource that will copy/move files locally. For example, I want to download jetty hightide and unzip it. Once done, copy all the files into a particular folder, like this:

# mv /var/tmp/jetty-hightide-7.4.5.v20110725/* /opt/jetty/

BTW, jettyhightide when unzipped, gives you a folder and inside that folder rest of the files are located. Hence unzip jetty-hightide-7.4.5.v20110725.zip -d /opt/jetty/ is useless because it will create a directory /opt/jetty/jetty-hightide-7.4.5.v20110725/* whereas what I really want is /opt/jetty/*. Hence I am looking for a local copy/move resource in Chef.


How to copy single file

First way

I use file statement to copy file (compile-time check)

file "/etc/init.d/someService" do
  owner 'root'
  group 'root'
  mode 0755
  content ::File.open("/home/someService").read
  action :create
end

here :

  • "/etc/init.d/someService" - target file,
  • "/home/someService" - source file

Also you can wrap ::File.open("/home/someService").read in lazy block

...
lazy { ::File.open("/home/someService").read }
...

Second way

User remote_file statement (run-time check)

remote_file "Copy service file" do 
  path "/etc/init.d/someService" 
  source "file:///home/someService"
  owner 'root'
  group 'root'
  mode 0755
end

Third way

Also you can use shell/batch

For-each directory

Dir[ "/some/directory/resources/**/*" ].each do |curr_path|
  file "/some/target/dir/#{Pathname.new(curr_path).basename}" do
    owner 'root'
    group 'root'
    mode 0755
    content lazy { IO.read(curr_path, mode: 'rb').read }
    action :create
  end if File.file?(curr_path)
  directory "/some/target/dir/#{File.dirname(curr_path)}" do
    path curr_path
    owner 'root'
    group 'root'
    mode 0755
    action :create
  end if File.directory?(curr_path)
end

This is just idea, because sub-paths in this example is not handled correctly.


I got it working by using bash resource as below:

bash "install_jettyhightide" do
  code <<-EOL
  unzip /var/tmp/jetty-hightide-7.4.5.v20110725.zip -d /opt/jetty/
  mv /opt/jetty/jetty-hightide-7.4.5.v20110725/* /opt/jetty/
  cp /opt/jetty/bin/jetty.sh /etc/init.d/jetty
  update-rc.d jetty defaults
  EOL
end

But I was really hoping for a chef way of doing it. copying/moving files locally would be the most generic task a sysadmin will need to do.


I know this question have already been answered, and discussed, but here is the method I use when creating files.

  1. First include the file under the cookbook's files/default folder
  2. Then on your recipe use the cookbook_file resource

e.g:

cookbook_file "/server/path/to/file.ext" do
  source "filename.ext"
  owner "root"
  group "root"
  mode 00600
  action :create_if_missing
end

From chef documentation: https://docs.chef.io/resources/cookbook_file/

The cookbook_file resource is used to transfer files from a sub-directory of the files/ directory in a cookbook to a specified path that is located on the host running the chef-client or chef-solo.