sshkit
sshkit copied to clipboard
Bug: upload! within an `as 'root'` block will fail.
The following will usually fail:
task :foo do
on roles(:web) do
as "root" do
upload! "/tmp/foo", "/var/bar/cuux"
end
end
end
Since scp will not su to root. Would you accept a PR that allows upload!
to upload to /tmp
and then mv
the file into place, if the current user has been switched?
I'd consider a helper function that wrapped both, but not a change to the upload!
api.
I haven't tested this, but maybe it would work?
on roles(:web) do |host|
host.user = "root"
upload! "/tmp/foo", "/var/bar/cuux"
end
@mattbrictson won't work if the root user can't login (Which is default for Ubuntu images an aws anyway).
Ah, then the helper method you described is probably the best bet.
What if the behaviour required an explicit option to be set. E.g.:
task :foo do
on roles(:web) do
as "root", file_transfer: true do
upload! "/tmp/foo", "/var/bar/cuux"
end
end
end
Not sure if I disagree with your stance btw. - I'm just thinking out loud here.
Here's a helper that I use in my own projects. Maybe we could adapt it to be useful for both of our cases and add it to core?
# Uploads the given string or file-like object to the current host
# context. Accepts :owner and :mode options that affect the permissions of the
# remote file.
#
def put(string_or_io, remote_path, opts={})
sudo_exec = ->(*cmd) {
cmd = [:sudo] + cmd if opts[:sudo]
execute *cmd
}
tmp_path = "/tmp/#{SecureRandom.uuid}"
owner = opts[:owner]
mode = opts[:mode]
source = if string_or_io.respond_to?(:read)
string_or_io
else
StringIO.new(string_or_io.to_s)
end
sudo_exec.call :mkdir, "-p", File.dirname(remote_path)
upload!(source, tmp_path)
sudo_exec.call(:mv, "-f", tmp_path, remote_path)
sudo_exec.call(:chown, owner, remote_path) if owner
sudo_exec.call(:chmod, mode, remote_path) if mode
end