synced_folders/rsync: move rsync logic out to helper
This commit is contained in:
parent
9b383740ba
commit
59218ded68
|
@ -324,7 +324,7 @@ module Vagrant
|
||||||
# Returns the state of this machine. The state is queried from the
|
# Returns the state of this machine. The state is queried from the
|
||||||
# backing provider, so it can be any arbitrary symbol.
|
# backing provider, so it can be any arbitrary symbol.
|
||||||
#
|
#
|
||||||
# @return [Symbol]
|
# @return [MachineState]
|
||||||
def state
|
def state
|
||||||
result = @provider.state
|
result = @provider.state
|
||||||
raise Errors::MachineStateInvalid if !result.is_a?(MachineState)
|
raise Errors::MachineStateInvalid if !result.is_a?(MachineState)
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
require_relative "../helper"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module SyncedFolderRSync
|
||||||
|
module Command
|
||||||
|
class Rsync < Vagrant.plugin("2", :command)
|
||||||
|
def self.synopsis
|
||||||
|
"syncs rsync synced folders to remote machine"
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute
|
||||||
|
opts = OptionParser.new do |o|
|
||||||
|
o.banner = "Usage: vagrant rsync [vm-name]"
|
||||||
|
o.separator ""
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse the options and return if we don't have any target.
|
||||||
|
argv = parse_options(opts)
|
||||||
|
return if !argv
|
||||||
|
|
||||||
|
# Go through each machine and perform the rsync
|
||||||
|
error = false
|
||||||
|
with_target_vms(argv) do |machine|
|
||||||
|
if !machine.communicate.ready?
|
||||||
|
machine.ui.error(I18n.t("vagrant.rsync_communicator_not_ready"))
|
||||||
|
error = true
|
||||||
|
next
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return error ? 1 : 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,66 @@
|
||||||
|
require "vagrant/util/subprocess"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module SyncedFolderRSync
|
||||||
|
# This is a helper that abstracts out the functionality of rsyncing
|
||||||
|
# folders so that it can be called from anywhere.
|
||||||
|
class RsyncHelper
|
||||||
|
def self.rsync_single(machine, ssh_info, opts)
|
||||||
|
# Folder info
|
||||||
|
guestpath = opts[:guestpath]
|
||||||
|
hostpath = opts[:hostpath]
|
||||||
|
|
||||||
|
# Connection information
|
||||||
|
username = ssh_info[:username]
|
||||||
|
host = ssh_info[:host]
|
||||||
|
rsh = [
|
||||||
|
"ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no",
|
||||||
|
ssh_info[:private_key_path].map { |p| "-i '#{p}'" },
|
||||||
|
].flatten.join(" ")
|
||||||
|
|
||||||
|
# Exclude some files by default, and any that might be configured
|
||||||
|
# by the user.
|
||||||
|
excludes = ['.vagrant/']
|
||||||
|
excludes += Array(opts[:exclude]).map(&:to_s) if opts[:exclude]
|
||||||
|
excludes.uniq!
|
||||||
|
|
||||||
|
# Build up the actual command to execute
|
||||||
|
command = [
|
||||||
|
"rsync",
|
||||||
|
"--verbose",
|
||||||
|
"--archive",
|
||||||
|
"-z",
|
||||||
|
excludes.map { |e| ["--exclude", e] },
|
||||||
|
"-e", rsh,
|
||||||
|
hostpath,
|
||||||
|
"#{username}@#{host}:#{guestpath}"
|
||||||
|
].flatten
|
||||||
|
command_opts = {}
|
||||||
|
|
||||||
|
# The working directory should be the root path
|
||||||
|
command_opts[:workdir] = machine.env.root_path.to_s
|
||||||
|
|
||||||
|
machine.ui.info(I18n.t(
|
||||||
|
"vagrant.rsync_folder", guestpath: guestpath, hostpath: hostpath))
|
||||||
|
if excludes.length > 1
|
||||||
|
machine.ui.info(I18n.t(
|
||||||
|
"vagrant.rsync_folder_excludes", excludes: excludes.inspect))
|
||||||
|
end
|
||||||
|
|
||||||
|
# If we have tasks to do before rsyncing, do those.
|
||||||
|
if machine.guest.capability?(:rsync_pre)
|
||||||
|
machine.guest.capability(:rsync_pre, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
r = Vagrant::Util::Subprocess.execute(*(command + [command_opts]))
|
||||||
|
if r.exit_code != 0
|
||||||
|
raise Vagrant::Errors::RSyncError,
|
||||||
|
command: command.join(" "),
|
||||||
|
guestpath: guestpath,
|
||||||
|
hostpath: hostpath,
|
||||||
|
stderr: r.stderr
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,6 +9,11 @@ module VagrantPlugins
|
||||||
The Rsync synced folder plugin will sync folders via rsync.
|
The Rsync synced folder plugin will sync folders via rsync.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
command("rsync", primary: false) do
|
||||||
|
require_relative "command/rsync"
|
||||||
|
Command::Rsync
|
||||||
|
end
|
||||||
|
|
||||||
synced_folder("rsync", 5) do
|
synced_folder("rsync", 5) do
|
||||||
require_relative "synced_folder"
|
require_relative "synced_folder"
|
||||||
SyncedFolder
|
SyncedFolder
|
||||||
|
|
|
@ -3,6 +3,8 @@ require "log4r"
|
||||||
require "vagrant/util/subprocess"
|
require "vagrant/util/subprocess"
|
||||||
require "vagrant/util/which"
|
require "vagrant/util/which"
|
||||||
|
|
||||||
|
require_relative "helper"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module SyncedFolderRSync
|
module SyncedFolderRSync
|
||||||
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
||||||
|
@ -33,65 +35,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
folders.each do |id, folder_opts|
|
folders.each do |id, folder_opts|
|
||||||
rsync_single(machine, ssh_info, folder_opts)
|
RsyncHelper.rsync_single(machine, ssh_info, folder_opts)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# rsync_single rsync's a single folder with the given options.
|
|
||||||
def rsync_single(machine, ssh_info, opts)
|
|
||||||
# Folder info
|
|
||||||
guestpath = opts[:guestpath]
|
|
||||||
hostpath = opts[:hostpath]
|
|
||||||
|
|
||||||
# Connection information
|
|
||||||
username = ssh_info[:username]
|
|
||||||
host = ssh_info[:host]
|
|
||||||
rsh = [
|
|
||||||
"ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no",
|
|
||||||
ssh_info[:private_key_path].map { |p| "-i '#{p}'" },
|
|
||||||
].flatten.join(" ")
|
|
||||||
|
|
||||||
# Exclude some files by default, and any that might be configured
|
|
||||||
# by the user.
|
|
||||||
excludes = ['.vagrant/']
|
|
||||||
excludes += Array(opts[:exclude]).map(&:to_s) if opts[:exclude]
|
|
||||||
excludes.uniq!
|
|
||||||
|
|
||||||
# Build up the actual command to execute
|
|
||||||
command = [
|
|
||||||
"rsync",
|
|
||||||
"--verbose",
|
|
||||||
"--archive",
|
|
||||||
"-z",
|
|
||||||
excludes.map { |e| ["--exclude", e] },
|
|
||||||
"-e", rsh,
|
|
||||||
hostpath,
|
|
||||||
"#{username}@#{host}:#{guestpath}"
|
|
||||||
].flatten
|
|
||||||
command_opts = {}
|
|
||||||
|
|
||||||
# The working directory should be the root path
|
|
||||||
command_opts[:workdir] = machine.env.root_path.to_s
|
|
||||||
|
|
||||||
machine.ui.info(I18n.t(
|
|
||||||
"vagrant.rsync_folder", guestpath: guestpath, hostpath: hostpath))
|
|
||||||
if excludes.length > 1
|
|
||||||
machine.ui.info(I18n.t(
|
|
||||||
"vagrant.rsync_folder_excludes", excludes: excludes.inspect))
|
|
||||||
end
|
|
||||||
|
|
||||||
# If we have tasks to do before rsyncing, do those.
|
|
||||||
if machine.guest.capability?(:rsync_pre)
|
|
||||||
machine.guest.capability(:rsync_pre, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
r = Vagrant::Util::Subprocess.execute(*(command + [command_opts]))
|
|
||||||
if r.exit_code != 0
|
|
||||||
raise Vagrant::Errors::RSyncError,
|
|
||||||
command: command.join(" "),
|
|
||||||
guestpath: guestpath,
|
|
||||||
hostpath: hostpath,
|
|
||||||
stderr: r.stderr
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -85,6 +85,9 @@ en:
|
||||||
%{names}
|
%{names}
|
||||||
provisioner_cleanup: |-
|
provisioner_cleanup: |-
|
||||||
Running cleanup tasks for '%{name}' provisioner...
|
Running cleanup tasks for '%{name}' provisioner...
|
||||||
|
rsync_communicator_not_ready: |-
|
||||||
|
The machine is reporting that it is not ready for rsync to
|
||||||
|
communiate with it. Verify that this machine is properly running.
|
||||||
rsync_folder: |-
|
rsync_folder: |-
|
||||||
Rsyncing folder: %{hostpath} => %{guestpath}
|
Rsyncing folder: %{hostpath} => %{guestpath}
|
||||||
rsync_folder_excludes: " - Exclude: %{excludes}"
|
rsync_folder_excludes: " - Exclude: %{excludes}"
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
require_relative "../../../base"
|
||||||
|
|
||||||
|
require Vagrant.source_root.join("plugins/synced_folders/rsync/helper")
|
||||||
|
|
||||||
|
describe VagrantPlugins::SyncedFolderRSync::RsyncHelper do
|
||||||
|
include_context "unit"
|
||||||
|
|
||||||
|
let(:iso_env) do
|
||||||
|
# We have to create a Vagrantfile so there is a root path
|
||||||
|
env = isolated_environment
|
||||||
|
env.vagrantfile("")
|
||||||
|
env.create_vagrant_env
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:guest) { double("guest") }
|
||||||
|
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
||||||
|
|
||||||
|
subject { described_class }
|
||||||
|
|
||||||
|
before do
|
||||||
|
machine.stub(guest: guest)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#rsync_single" do
|
||||||
|
let(:result) { Vagrant::Util::Subprocess::Result.new(0, "", "") }
|
||||||
|
|
||||||
|
let(:ssh_info) {{
|
||||||
|
private_key_path: [],
|
||||||
|
}}
|
||||||
|
let(:opts) { {} }
|
||||||
|
let(:ui) { machine.ui }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Vagrant::Util::Subprocess.stub(execute: result)
|
||||||
|
|
||||||
|
guest.stub(capability?: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't raise an error if it succeeds" do
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises an error if the exit code is non-zero" do
|
||||||
|
Vagrant::Util::Subprocess.stub(
|
||||||
|
execute: Vagrant::Util::Subprocess::Result.new(1, "", ""))
|
||||||
|
|
||||||
|
expect {subject.rsync_single(machine, ssh_info, opts) }.
|
||||||
|
to raise_error(Vagrant::Errors::RSyncError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes within the root path" do
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
||||||
|
expect(args.last).to be_kind_of(Hash)
|
||||||
|
|
||||||
|
opts = args.last
|
||||||
|
expect(opts[:workdir]).to eql(machine.env.root_path.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "executes the rsync_pre capability first if it exists" do
|
||||||
|
guest.should_receive(:capability?).with(:rsync_pre).and_return(true)
|
||||||
|
guest.should_receive(:capability).with(:rsync_pre, opts).ordered
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).ordered.and_return(result)
|
||||||
|
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "excluding files" do
|
||||||
|
it "excludes files if given as a string" do
|
||||||
|
opts[:exclude] = "foo"
|
||||||
|
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
||||||
|
index = args.find_index("foo")
|
||||||
|
expect(index).to be > 0
|
||||||
|
expect(args[index-1]).to eql("--exclude")
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "excludes multiple files" do
|
||||||
|
opts[:exclude] = ["foo", "bar"]
|
||||||
|
|
||||||
|
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
||||||
|
index = args.find_index("foo")
|
||||||
|
expect(index).to be > 0
|
||||||
|
expect(args[index-1]).to eql("--exclude")
|
||||||
|
|
||||||
|
index = args.find_index("bar")
|
||||||
|
expect(index).to be > 0
|
||||||
|
expect(args[index-1]).to eql("--exclude")
|
||||||
|
end
|
||||||
|
|
||||||
|
subject.rsync_single(machine, ssh_info, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -16,6 +16,8 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do
|
||||||
let(:host) { double("host") }
|
let(:host) { double("host") }
|
||||||
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
||||||
|
|
||||||
|
let(:helper_class) { VagrantPlugins::SyncedFolderRSync::RsyncHelper }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
machine.env.stub(host: host)
|
machine.env.stub(host: host)
|
||||||
machine.stub(guest: guest)
|
machine.stub(guest: guest)
|
||||||
|
@ -55,7 +57,7 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do
|
||||||
]
|
]
|
||||||
|
|
||||||
folders.each do |_, opts|
|
folders.each do |_, opts|
|
||||||
subject.should_receive(:rsync_single).
|
helper_class.should_receive(:rsync_single).
|
||||||
with(machine, ssh_info, opts).
|
with(machine, ssh_info, opts).
|
||||||
ordered
|
ordered
|
||||||
end
|
end
|
||||||
|
@ -63,81 +65,4 @@ describe VagrantPlugins::SyncedFolderRSync::SyncedFolder do
|
||||||
subject.enable(machine, folders, {})
|
subject.enable(machine, folders, {})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#rsync_single" do
|
|
||||||
let(:result) { Vagrant::Util::Subprocess::Result.new(0, "", "") }
|
|
||||||
|
|
||||||
let(:ssh_info) {{
|
|
||||||
private_key_path: [],
|
|
||||||
}}
|
|
||||||
let(:opts) { {} }
|
|
||||||
let(:ui) { machine.ui }
|
|
||||||
|
|
||||||
before do
|
|
||||||
Vagrant::Util::Subprocess.stub(execute: result)
|
|
||||||
|
|
||||||
guest.stub(capability?: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "doesn't raise an error if it succeeds" do
|
|
||||||
subject.rsync_single(machine, ssh_info, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "raises an error if the exit code is non-zero" do
|
|
||||||
Vagrant::Util::Subprocess.stub(
|
|
||||||
execute: Vagrant::Util::Subprocess::Result.new(1, "", ""))
|
|
||||||
|
|
||||||
expect {subject.rsync_single(machine, ssh_info, opts) }.
|
|
||||||
to raise_error(Vagrant::Errors::RSyncError)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "executes within the root path" do
|
|
||||||
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
|
||||||
expect(args.last).to be_kind_of(Hash)
|
|
||||||
|
|
||||||
opts = args.last
|
|
||||||
expect(opts[:workdir]).to eql(machine.env.root_path.to_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
subject.rsync_single(machine, ssh_info, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "executes the rsync_pre capability first if it exists" do
|
|
||||||
guest.should_receive(:capability?).with(:rsync_pre).and_return(true)
|
|
||||||
guest.should_receive(:capability).with(:rsync_pre, opts).ordered
|
|
||||||
Vagrant::Util::Subprocess.should_receive(:execute).ordered.and_return(result)
|
|
||||||
|
|
||||||
subject.rsync_single(machine, ssh_info, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
context "excluding files" do
|
|
||||||
it "excludes files if given as a string" do
|
|
||||||
opts[:exclude] = "foo"
|
|
||||||
|
|
||||||
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
|
||||||
index = args.find_index("foo")
|
|
||||||
expect(index).to be > 0
|
|
||||||
expect(args[index-1]).to eql("--exclude")
|
|
||||||
end
|
|
||||||
|
|
||||||
subject.rsync_single(machine, ssh_info, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "excludes multiple files" do
|
|
||||||
opts[:exclude] = ["foo", "bar"]
|
|
||||||
|
|
||||||
Vagrant::Util::Subprocess.should_receive(:execute).with do |*args|
|
|
||||||
index = args.find_index("foo")
|
|
||||||
expect(index).to be > 0
|
|
||||||
expect(args[index-1]).to eql("--exclude")
|
|
||||||
|
|
||||||
index = args.find_index("bar")
|
|
||||||
expect(index).to be > 0
|
|
||||||
expect(args[index-1]).to eql("--exclude")
|
|
||||||
end
|
|
||||||
|
|
||||||
subject.rsync_single(machine, ssh_info, opts)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue