chef 的には cookbook_file とかでなんとかするべき
definitions/rsync.rb
class ::Chef
class Definition
# rsync files from a host to localhost
#
# HOW TO USE:
#
# 1)
#
# rsync "#{name}" do
# from "#{hostname}:#{from_path}"
# to "#{to_path}"
# end
#
# rsync "#{name}" do
# from "#{from_path}"
# to "#{hostname}:#{to_path}"
# end
#
# 2) notifies must specify `execute` not `rsync`
#
# cookbook_file "/tmp/foo" do
# source "tmp/foo"
# notifies :run, "execute[#{name}]"
# end
#
# rsync "#{name}" do
# from "#{from_path}"
# to "#{hostname}:#{to_path}"
# end
#
# OPTIONS:
#
# * command
# * rsync command with option. Default: /usr/bin/rsync -avzl --exclude=.git --delete -e ssh'
# * from:
# * rsync src.
# * to:
# * rsync dest.
#
# Other options are same with `execute` resource.
# See https://docs.chef.io/resource_execute.html
#
# NOTICE:
#
# Chef orginally does not support to deploy files from remote hosts via rsync.
# That said, rsync way should be removed sooner or later, and using only built-in resouces
# such as `remote_file`, `cookbook_file`, `template`, `remote_directory`is better.
module Rsync
# default command
def default_command
'/usr/bin/rsync -avzl --exclude=.git --delete -e ssh'
end
module_function :default_command
# build rsync command
#
# @param [String] command Default is self.default_command
# @param [String] from
# @param [String] to
def build_command(command: nil, from: , to: )
command ||= self.default_command
"#{command} #{from} #{to}"
end
module_function :build_command
end
end
end
opts = {
:command => ::Chef::Definition::Rsync.default_command,
:from => nil,
:to => nil,
}
define :rsync, opts do
raise ArgumentError, "`to` is missing for rsync" unless params[:to]
name = params[:name]
from = params[:from] || params[:name] # hostname:/path/to/file
to = params[:to]
from = from.call if from.is_a?(Chef::DelayedEvaluator)
to = to.call if to.is_a?(Chef::DelayedEvaluator)
rsync = ::Chef::Definition::Rsync.build_command(
command: params[:command],
from: from,
to: to,
)
execute_params = params.dup.tap do |params|
params.delete(:name)
params.delete(:command)
params.delete(:from)
params.delete(:to)
end
execute_params[:command] ||= rsync
# ToDo: find better way to achieve idempotence
execute_params[:only_if] ||= "test $(#{rsync} -n 2>&1 | wc -l) -gt 4" # assume -v is used
execute name do
execute_params.each {|key, val| send(key, *val) }
end
end