Merge pull request #10263 from chrisroberts/e-winrm-extensions

Add winrm and upload commands
This commit is contained in:
Chris Roberts 2018-10-09 14:42:54 -07:00 committed by GitHub
commit 93c2f0f497
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1923 additions and 1 deletions

View File

@ -816,6 +816,22 @@ module Vagrant
error_key(:unimplemented_provider_action) error_key(:unimplemented_provider_action)
end end
class UploadInvalidCompressionType < VagrantError
error_key(:upload_invalid_compression_type)
end
class UploadMissingExtractCapability < VagrantError
error_key(:upload_missing_extract_capability)
end
class UploadMissingTempCapability < VagrantError
error_key(:upload_missing_temp_capability)
end
class UploadSourceMissing < VagrantError
error_key(:upload_source_missing)
end
class VagrantInterrupt < VagrantError class VagrantInterrupt < VagrantError
error_key(:interrupted) error_key(:interrupted)
end end
@ -968,6 +984,10 @@ module Vagrant
error_key(:power_off, "vagrant.actions.vm.export") error_key(:power_off, "vagrant.actions.vm.export")
end end
class WinRMInvalidCommunicator < VagrantError
error_key(:winrm_invalid_communicator)
end
class WSLVagrantVersionMismatch < VagrantError class WSLVagrantVersionMismatch < VagrantError
error_key(:wsl_vagrant_version_mismatch) error_key(:wsl_vagrant_version_mismatch)
end end

View File

@ -0,0 +1,236 @@
require 'optparse'
require "rubygems/package"
module VagrantPlugins
module CommandUpload
class Command < Vagrant.plugin("2", :command)
VALID_COMPRESS_TYPES = [:tgz, :zip].freeze
def self.synopsis
"upload to machine via communicator"
end
def execute
options = {}
opts = OptionParser.new do |o|
o.banner = "Usage: vagrant upload [options] <source> [destination] [name|id]"
o.separator ""
o.separator "Options:"
o.separator ""
o.on("-t", "--temporary", "Upload source to temporary directory") do |t|
options[:temporary] = t
end
o.on("-c", "--compress", "Use gzip compression for upload") do |c|
options[:compress] = c
end
o.on("-C", "--compression-type=TYPE", "Type of compression to use (#{VALID_COMPRESS_TYPES.join(", ")})") do |c|
options[:compression_type] = c.to_sym
options[:compress] = true
end
end
argv = parse_options(opts)
return if !argv
case argv.size
when 3
source, destination, guest = argv
when 2, 1
source = argv[0]
if @env.active_machines.map(&:first).map(&:to_s).include?(argv[1])
guest = argv[1]
else
destination = argv[1]
end
else
raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp
end
# NOTE: We do this to handle paths on Windows like: "..\space dir\"
# because the final separater acts to escape the quote and ends up
# in the source value.
source = source.sub(/["']$/, "")
destination ||= File.basename(source)
if File.file?(source)
type = :file
elsif File.directory?(source)
type = :directory
else
raise Vagrant::Errors::UploadSourceMissing,
source: source
end
with_target_vms(guest, single_target: true) do |machine|
if options[:temporary]
if !machine.guest.capability?(:create_tmp_path)
raise Vagrant::Errors::UploadMissingTempCapability
end
extension = File.extname(source) if type == :file
destination = machine.guest.capability(:create_tmp_path, type: type, extension: extension)
end
if options[:compress]
compression_setup!(machine, options)
@env.ui.info(I18n.t("vagrant.commands.upload.compress",
source: source,
type: options[:compression_type]
))
destination_decompressed = destination
destination = machine.guest.capability(:create_tmp_path, type: :file, extension: ".#{options[:compression_type]}")
source_display = source
source = options[:compression_type] == :zip ? compress_source_zip(source) : compress_source_tgz(source)
end
@env.ui.info(I18n.t("vagrant.commands.upload.start",
source: source,
destination: destination
))
# If the source is a directory, attach a `/.` to the end so we
# upload the contents to the destination instead of within a
# folder at the destination
if File.directory?(source) && !source.end_with?(".")
upload_source = File.join(source, ".")
else
upload_source = source
end
machine.communicate.upload(upload_source, destination)
if options[:compress]
@env.ui.info(I18n.t("vagrant.commands.upload.decompress",
destination: destination_decompressed,
type: options[:compression_type]
))
machine.guest.capability(options[:decompression_method], destination, destination_decompressed, type: type)
destination = destination_decompressed
FileUtils.rm(source)
source = source_display
end
end
@env.ui.info(I18n.t("vagrant.commands.upload.complete",
source: source,
destination: destination
))
# Success, exit status 0
0
end
# Setup compression options and validate host and guest have capability
# to handle compression
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [Hash] options Command options
def compression_setup!(machine, options)
if !options[:compression_type]
if machine.guest.capability_host_chain.first[0] == :windows
options[:compression_type] = :zip
else
options[:compression_type] = :tgz
end
end
if !VALID_COMPRESS_TYPES.include?(options[:compression_type])
raise Vagrant::Errors::UploadInvalidCompressionType,
type: options[:compression_type],
valid_types: VALID_COMPRESS_TYPES.join(", ")
end
options[:decompression_method] = "decompress_#{options[:compression_type]}".to_sym
if !machine.guest.capability?(options[:decompression_method])
raise Vagrant::Errors::UploadMissingExtractCapability,
type: options[:compression_type]
end
end
# Compress path using zip into temporary file
#
# @param [String] path Path to compress
# @return [String] path to compressed file
def compress_source_zip(path)
require "zip"
zipfile = Tempfile.create(["vagrant", ".zip"])
zipfile.close
if File.file?(path)
source_items = [path]
else
source_items = Dir.glob(File.join(path, "**", "**", "*"))
end
c_dir = nil
Zip::File.open(zipfile.path, Zip::File::CREATE) do |zip|
source_items.each do |source_item|
next if File.directory?(source_item)
trim_item = source_item.sub(path, "").sub(%r{^[/\\]}, "")
dirname = File.dirname(trim_item)
zip.mkdir dirname if c_dir != dirname
c_dir = dirname
zip.get_output_stream(trim_item) do |f|
source_file = File.open(source_item, "rb")
while data = source_file.read(2048)
f.write(data)
end
end
end
end
zipfile.path
end
# Compress path using tar and gzip into temporary file
#
# @param [String] path Path to compress
# @return [String] path to compressed file
def compress_source_tgz(path)
tarfile = Tempfile.create(["vagrant", ".tar"])
tarfile.close
tarfile = File.open(tarfile.path, "wb+")
tgzfile = Tempfile.create(["vagrant", ".tgz"])
tgzfile.close
tgzfile = File.open(tgzfile.path, "wb")
tar = Gem::Package::TarWriter.new(tarfile)
tgz = Zlib::GzipWriter.new(tgzfile)
if File.file?(path)
tar.add_file(File.basename(path), File.stat(path).mode) do |io|
File.open(path, "rb") do |file|
while bytes = file.read(4096)
io.write(bytes)
end
end
end
else
Dir.glob(File.join(path, "**/**/*")).each do |item|
rel_path = item.sub(path, "")
item_mode = File.stat(item).mode
if File.directory?(item)
tar.mkdir(rel_path, item_mode)
else
tar.add_file(rel_path, item_mode) do |io|
File.open(item, "rb") do |file|
while bytes = file.read(4096)
io.write(bytes)
end
end
end
end
end
end
tar.close
tarfile.rewind
while bytes = tarfile.read(4096)
tgz.write bytes
end
tgz.close
tgzfile.close
tarfile.close
File.delete(tarfile.path)
tgzfile.path
end
end
end
end

View File

@ -0,0 +1,17 @@
require "vagrant"
module VagrantPlugins
module CommandUpload
class Plugin < Vagrant.plugin("2")
name "upload command"
description <<-DESC
The `upload` command uploads files to guest via communicator
DESC
command("upload") do
require File.expand_path("../command", __FILE__)
Command
end
end
end
end

View File

@ -0,0 +1,69 @@
require 'optparse'
require "vagrant/util/safe_puts"
module VagrantPlugins
module CommandWinRM
class Command < Vagrant.plugin("2", :command)
include Vagrant::Util::SafePuts
def self.synopsis
"executes commands on a machine via WinRM"
end
def execute
options = {
command: [],
shell: :powershell
}
opts = OptionParser.new do |o|
o.banner = "Usage: vagrant winrm [options] [name|id]"
o.separator ""
o.separator "Options:"
o.separator ""
o.on("-c", "--command COMMAND", "Execute a WinRM command directly") do |c|
options[:command] << c
end
o.on("-e", "--elevated", "Run with elevated credentials") do |e|
options[:elevated] = true
end
o.on("-s", "--shell SHELL", [:powershell, :cmd], "Use specified shell (powershell, cmd)") do |s|
options[:shell] = s
end
end
argv = parse_options(opts)
return if !argv
with_target_vms(argv, single_target: true) do |machine|
if machine.config.vm.communicator != :winrm
raise Vagrant::Errors::WinRMInvalidCommunicator
end
opts = {
shell: options[:shell],
elevated: !!options[:elevated]
}
options[:command].each do |cmd|
begin
machine.communicate.execute(cmd, opts) do |type, data|
io = type == :stderr ? $stderr : $stdout
safe_puts(data, io: io, printer: :print)
end
rescue VagrantPlugins::CommunicatorWinRM::Errors::WinRMBadExitStatus
return 1
end
end
end
# Success, exit status 0
0
end
end
end
end

View File

@ -0,0 +1,17 @@
require "vagrant"
module VagrantPlugins
module CommandWinRM
class Plugin < Vagrant.plugin("2")
name "winrm command"
description <<-DESC
The `winrm` command executes commands on a machine via WinRM
DESC
command("winrm") do
require File.expand_path("../command", __FILE__)
Command
end
end
end
end

View File

@ -0,0 +1,125 @@
require 'optparse'
require "vagrant/util/safe_puts"
require_relative "../../communicators/winrm/helper"
module VagrantPlugins
module CommandWinRMConfig
class Command < Vagrant.plugin("2", :command)
include Vagrant::Util::SafePuts
def self.synopsis
"outputs WinRM configuration to connect to the machine"
end
def convert_win_paths(paths)
paths.map! { |path| Vagrant::Util::Platform.format_windows_path(path, :disable_unc) }
end
def execute
options = {}
opts = OptionParser.new do |o|
o.banner = "Usage: vagrant winrm-config [options] [name|id]"
o.separator ""
o.separator "Options:"
o.separator ""
o.on("--host NAME", "Name the host for the config") do |h|
options[:host] = h
end
end
argv = parse_options(opts)
return if !argv
with_target_vms(argv) do |machine|
winrm_info = CommunicatorWinRM::Helper.winrm_info(machine)
raise Vagrant::Errors::WinRMNotRead if winrm_info.nil?
rdp_info = get_rdp_info(machine) || {}
variables = {
host_key: options[:host] || machine.name || "vagrant",
rdp_host: rdp_info[:host] || winrm_info[:host],
rdp_port: rdp_info[:port],
rdp_user: rdp_info[:username],
rdp_pass: rdp_info[:password],
winrm_host: winrm_info[:host],
winrm_port: winrm_info[:port],
winrm_user: machine.config.winrm.username,
winrm_password: machine.config.winrm.password
}
template = "commands/winrm_config/config"
config = Vagrant::Util::TemplateRenderer.render(template, variables)
machine.ui.machine("winrm-config", config)
safe_puts(config)
safe_puts
end
# Success, exit status 0
0
end
protected
# Generate RDP information for machine
#
# @param [Vagrant::Machine] machine Guest machine
# @return [Hash, nil]
def get_rdp_info(machine)
rdp_info = {}
if machine.provider.capability?(:rdp_info)
rdp_info = machine.provider.capability(:rdp_info)
rdp_info ||= {}
end
ssh_info = machine.ssh_info || {}
if !rdp_info[:username]
username = ssh_info[:username]
if machine.config.vm.communicator == :winrm
username = machine.config.winrm.username
end
rdp_info[:username] = username
end
if !rdp_info[:password]
password = ssh_info[:password]
if machine.config.vm.communicator == :winrm
password = machine.config.winrm.password
end
rdp_info[:password] = password
end
rdp_info[:host] ||= ssh_info[:host]
rdp_info[:port] ||= machine.config.rdp.port
rdp_info[:username] ||= machine.config.rdp.username
if rdp_info[:host] == "127.0.0.1"
# We need to find a forwarded port...
search_port = machine.config.rdp.search_port
ports = nil
if machine.provider.capability?(:forwarded_ports)
ports = machine.provider.capability(:forwarded_ports)
else
ports = {}.tap do |result|
machine.config.vm.networks.each do |type, netopts|
next if type != :forwarded_port
next if !netopts[:host]
result[netopts[:host]] = netopts[:guest]
end
end
end
ports = ports.invert
port = ports[search_port]
rdp_info[:port] = port
return nil if !port
end
rdp_info
end
end
end
end

View File

@ -0,0 +1,17 @@
require "vagrant"
module VagrantPlugins
module CommandWinRMConfig
class Plugin < Vagrant.plugin("2")
name "winrm-config command"
description <<-DESC
The `winrm-config` command dumps WinRM configuration information
DESC
command("winrm-config") do
require File.expand_path("../command", __FILE__)
Command
end
end
end
end

View File

@ -0,0 +1,77 @@
module VagrantPlugins
module GuestBSD
module Cap
class FileSystem
# Create a temporary file or directory on the guest
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [Hash] opts Path options
# @return [String] path to temporary file or directory
def self.create_tmp_path(machine, opts)
template = "vagrant"
cmd = ["mktemp"]
if opts[:type] == :directory
cmd << "-d"
end
cmd << "-t"
cmd << template
tmp_path = ""
machine.communicate.execute(cmd.join(" ")) do |type, data|
if type == :stdout
tmp_path << data
end
end
tmp_path.strip
end
# Decompress tgz file on guest to given location
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [String] compressed_file Path to compressed file on guest
# @param [String] destination Path for decompressed files on guest
def self.decompress_tgz(machine, compressed_file, destination, opts={})
comm = machine.communicate
extract_dir = create_tmp_path(machine, type: :directory)
cmds = []
if opts[:type] == :directory
cmds << "mkdir -p '#{destination}'"
else
cmds << "mkdir -p '#{File.dirname(destination)}'"
end
cmds += [
"tar -C '#{extract_dir}' -xzf '#{compressed_file}'",
"mv '#{extract_dir}'/* '#{destination}'",
"rm -f '#{compressed_file}'",
"rm -rf '#{extract_dir}'"
]
cmds.each{ |cmd| comm.execute(cmd) }
true
end
# Decompress zip file on guest to given location
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [String] compressed_file Path to compressed file on guest
# @param [String] destination Path for decompressed files on guest
def self.decompress_zip(machine, compressed_file, destination, opts={})
comm = machine.communicate
extract_dir = create_tmp_path(machine, type: :directory)
cmds = []
if opts[:type] == :directory
cmds << "mkdir -p '#{destination}'"
else
cmds << "mkdir -p '#{File.dirname(destination)}'"
end
cmds += [
"unzip '#{compressed_file}' -d '#{extract_dir}'",
"mv '#{extract_dir}'/* '#{destination}'",
"rm -f '#{compressed_file}'",
"rm -rf '#{extract_dir}'"
]
cmds.each{ |cmd| comm.execute(cmd) }
true
end
end
end
end
end

View File

@ -11,6 +11,21 @@ module VagrantPlugins
Guest Guest
end end
guest_capability(:bsd, :create_tmp_path) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:bsd, :decompress_tgz) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:bsd, :decompress_zip) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:bsd, :halt) do guest_capability(:bsd, :halt) do
require_relative "cap/halt" require_relative "cap/halt"
Cap::Halt Cap::Halt

View File

@ -0,0 +1,79 @@
module VagrantPlugins
module GuestLinux
module Cap
class FileSystem
# Create a temporary file or directory on the guest
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [Hash] opts Path options
# @return [String] path to temporary file or directory
def self.create_tmp_path(machine, opts)
template = "vagrant-XXXXXX"
if opts[:extension]
template << opts[:extension].to_s
end
cmd = ["mktemp", "--tmpdir"]
if opts[:type] == :directory
cmd << "-d"
end
cmd << template
tmp_path = ""
machine.communicate.execute(cmd.join(" ")) do |type, data|
if type == :stdout
tmp_path << data
end
end
tmp_path.strip
end
# Decompress tgz file on guest to given location
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [String] compressed_file Path to compressed file on guest
# @param [String] destination Path for decompressed files on guest
def self.decompress_tgz(machine, compressed_file, destination, opts={})
comm = machine.communicate
extract_dir = create_tmp_path(machine, type: :directory)
cmds = []
if opts[:type] == :directory
cmds << "mkdir -p '#{destination}'"
else
cmds << "mkdir -p '#{File.dirname(destination)}'"
end
cmds += [
"tar -C '#{extract_dir}' -xzf '#{compressed_file}'",
"mv '#{extract_dir}'/* '#{destination}'",
"rm -f '#{compressed_file}'",
"rm -rf '#{extract_dir}'"
]
cmds.each{ |cmd| comm.execute(cmd) }
true
end
# Decompress zip file on guest to given location
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [String] compressed_file Path to compressed file on guest
# @param [String] destination Path for decompressed files on guest
def self.decompress_zip(machine, compressed_file, destination, opts={})
comm = machine.communicate
extract_dir = create_tmp_path(machine, type: :directory)
cmds = []
if opts[:type] == :directory
cmds << "mkdir -p '#{destination}'"
else
cmds << "mkdir -p '#{File.dirname(destination)}'"
end
cmds += [
"unzip '#{compressed_file}' -d '#{extract_dir}'",
"mv '#{extract_dir}'/* '#{destination}'",
"rm -f '#{compressed_file}'",
"rm -rf '#{extract_dir}'"
]
cmds.each{ |cmd| comm.execute(cmd) }
true
end
end
end
end
end

View File

@ -16,6 +16,21 @@ module VagrantPlugins
Cap::ChooseAddressableIPAddr Cap::ChooseAddressableIPAddr
end end
guest_capability(:linux, :create_tmp_path) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:linux, :decompress_tgz) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:linux, :decompress_zip) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:linux, :halt) do guest_capability(:linux, :halt) do
require_relative "cap/halt" require_relative "cap/halt"
Cap::Halt Cap::Halt

View File

@ -0,0 +1,77 @@
module VagrantPlugins
module GuestSolaris
module Cap
class FileSystem
# Create a temporary file or directory on the guest
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [Hash] opts Path options
# @return [String] path to temporary file or directory
def self.create_tmp_path(machine, opts)
template = "vagrant-XXXXXX"
cmd = ["mktemp"]
if opts[:type] == :directory
cmd << "-d"
end
cmd << "-t"
cmd << template
tmp_path = ""
machine.communicate.execute(cmd.join(" ")) do |type, data|
if type == :stdout
tmp_path << data
end
end
tmp_path.strip
end
# Decompress tgz file on guest to given location
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [String] compressed_file Path to compressed file on guest
# @param [String] destination Path for decompressed files on guest
def self.decompress_tgz(machine, compressed_file, destination, opts={})
comm = machine.communicate
extract_dir = create_tmp_path(machine, type: :directory)
cmds = []
if opts[:type] == :directory
cmds << "mkdir -p '#{destination}'"
else
cmds << "mkdir -p '#{File.dirname(destination)}'"
end
cmds += [
"tar xzf '#{compressed_file}' -C '#{extract_dir}'",
"mv '#{extract_dir}'/* '#{destination}'",
"rm -f '#{compressed_file}'",
"rm -rf '#{extract_dir}'"
]
cmds.each{ |cmd| comm.execute(cmd) }
true
end
# Decompress zip file on guest to given location
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [String] compressed_file Path to compressed file on guest
# @param [String] destination Path for decompressed files on guest
def self.decompress_zip(machine, compressed_file, destination, opts={})
comm = machine.communicate
extract_dir = create_tmp_path(machine, type: :directory)
cmds = []
if opts[:type] == :directory
cmds << "mkdir -p '#{destination}'"
else
cmds << "mkdir -p '#{File.dirname(destination)}'"
end
cmds += [
"unzip '#{compressed_file}' -d '#{extract_dir}'",
"mv '#{extract_dir}'/* '#{destination}'",
"rm -f '#{compressed_file}'",
"rm -rf '#{extract_dir}'"
]
cmds.each{ |cmd| comm.execute(cmd) }
true
end
end
end
end
end

View File

@ -16,6 +16,21 @@ module VagrantPlugins
Guest Guest
end end
guest_capability(:solaris, :create_tmp_path) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:solaris, :decompress_tgz) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:solaris, :decompress_zip) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:solaris, :change_host_name) do guest_capability(:solaris, :change_host_name) do
require_relative "cap/change_host_name" require_relative "cap/change_host_name"
Cap::ChangeHostName Cap::ChangeHostName

View File

@ -0,0 +1,65 @@
module VagrantPlugins
module GuestWindows
module Cap
class FileSystem
# Create a temporary file or directory on the guest
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [Hash] opts Path options
# @return [String] path to temporary file or directory
def self.create_tmp_path(machine, opts)
comm = machine.communicate
path = ""
cmd = "Write-Output ([System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), " \
"[System.IO.Path]::GetRandomFileName())) | Out-String -Width 2048"
comm.execute(cmd, shell: :powershell) do |type, data|
if type == :stdout
path << data
end
end
path.strip!
if opts[:extension]
path << opts[:extension].to_s
end
if opts[:type] == :directory
comm.execute("[System.IO.Directory]::CreateDirectory('#{path}')")
end
path
end
# Decompress zip file on guest to given location
#
# @param [Vagrant::Machine] machine Vagrant guest machine
# @param [String] compressed_file Path to compressed file on guest
# @param [String] destination Path for decompressed files on guest
def self.decompress_zip(machine, compressed_file, destination, opts={})
comm = machine.communicate
extract_dir = create_tmp_path(machine, type: :directory)
cmds = []
destination = destination.tr("/", "\\")
if opts[:type] == :directory
cmds << "New-Item -ItemType Directory -Force -Path \"#{destination}\""
else
d_parts = destination.split("\\")
d_parts.pop
parent_dir = d_parts.join("\\") + "\\"
cmds << "New-Item -ItemType Directory -Force -Path \"#{parent_dir}\""
end
cmd = "$f = \"#{compressed_file}\"; $d = \"#{extract_dir}\"; "
cmd << '$s = New-Object -ComObject "Shell.Application"; $z = $s.NameSpace($f); '
cmd << 'foreach($i in $z.items()){ $s.Namespace($d).copyhere($i); }'
cmds << cmd
cmds += [
"Move-Item -Force -Path \"#{extract_dir}\\*\" -Destination \"#{destination}\\\"",
"Remove-Item -Path \"#{compressed_file}\" -Force",
"Remove-Item -Path \"#{extract_dir}\" -Recurse -Force"
]
cmds.each do |cmd|
comm.execute(cmd, shell: :powershell)
end
true
end
end
end
end
end

View File

@ -34,6 +34,16 @@ module VagrantPlugins
Cap::Halt Cap::Halt
end end
guest_capability(:windows, :create_tmp_path) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:windows, :decompress_zip) do
require_relative "cap/file_system"
Cap::FileSystem
end
guest_capability(:windows, :mount_virtualbox_shared_folder) do guest_capability(:windows, :mount_virtualbox_shared_folder) do
require_relative "cap/mount_shared_folder" require_relative "cap/mount_shared_folder"
Cap::MountSharedFolder Cap::MountSharedFolder

View File

@ -0,0 +1,11 @@
Host <%= host_key %>
HostName <%= winrm_host %>
User <%= winrm_user %>
Password <%= winrm_password %>
Port <%= winrm_port %>
<% if rdp_port -%>
RDPHostName <%= rdp_host %>
RDPPort <%= rdp_port %>
RDPUser <%= rdp_user %>
RDPPassword <%= rdp_pass %>
<% end -%>

View File

@ -1462,6 +1462,8 @@ en:
your current setup. Please verify you have all the proper your current setup. Please verify you have all the proper
prerequisites for using this shared folder type and try again. prerequisites for using this shared folder type and try again.
test_key: |-
test value
triggers_run_fail: |- triggers_run_fail: |-
Trigger run failed Trigger run failed
triggers_guest_not_running: |- triggers_guest_not_running: |-
@ -1489,6 +1491,24 @@ en:
'%{provider}', but this provider doesn't support this action. This '%{provider}', but this provider doesn't support this action. This
is probably a bug in either the provider or the plugin calling this is probably a bug in either the provider or the plugin calling this
action, and should be reported. action, and should be reported.
upload_invalid_compression_type: |-
The compression type requested for upload (`%{type}`) is not a
supported value. Try uploading again using a valid compression
type.
Supported types: %{valid_types}
upload_missing_extract_capability: |-
The guest does not provide extraction capability for the requested
compression type (`%{type}`). Try a different compression type or
upload without compression.
upload_missing_temp_capability: |-
The guest does not provide temporary path capabilities. Please
try the upload again without requesting a temporary path.
upload_source_missing: |-
The source path provided for upload cannot be found. Please validate
the source location for upload an try again.
Source Path: %{source}
vagrantfile_exists: |- vagrantfile_exists: |-
`Vagrantfile` already exists in this directory. Remove it before `Vagrantfile` already exists in this directory. Remove it before
running `vagrant init`. running `vagrant init`.
@ -1685,7 +1705,9 @@ en:
vm_not_running: |- vm_not_running: |-
VM must be running to open SSH connection. Run `vagrant up` VM must be running to open SSH connection. Run `vagrant up`
to start the virtual machine. to start the virtual machine.
test_key: "test value" winrm_invalid_communicator: |-
The winrm command requires a WinRM communicator to be used when connecting
to the guest. Please update your configuration and try the command again.
wsl_vagrant_version_mismatch: |- wsl_vagrant_version_mismatch: |-
Vagrant cannot currently enable access to manage machines within the Windows Vagrant cannot currently enable access to manage machines within the Windows
environment because the version of Vagrant installed on Windows does not environment because the version of Vagrant installed on Windows does not
@ -2025,6 +2047,18 @@ en:
up: up:
upping: |- upping: |-
Bringing machine '%{name}' up with '%{provider}' provider... Bringing machine '%{name}' up with '%{provider}' provider...
upload:
compress: |-
Compressing %{source} to %{type} for upload...
complete: |-
Upload has completed successfully!
Source: %{source}
Destination: %{destination}
decompress: |-
Decompressing %{type} upload to %{destination}...
start: |-
Uploading %{source} to %{destination}
validate: validate:
success: |- success: |-
Vagrantfile validated successfully. Vagrantfile validated successfully.

View File

@ -0,0 +1,242 @@
require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/commands/upload/command")
describe VagrantPlugins::CommandUpload::Command do
include_context "unit"
include_context "virtualbox"
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", capability_host_chain: guest_chain) }
let(:host) { double("host", capability_host_chain: host_chain) }
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
let(:communicator) { double("communicator") }
let(:host_chain){ [[]] }
let(:guest_chain){ [[]] }
let(:argv) { [] }
let(:config) {
double("config")
}
subject { described_class.new(argv, iso_env) }
before do
allow(machine).to receive(:communicate).and_return(communicator)
allow(machine).to receive(:config).and_return(config)
allow(subject).to receive(:with_target_vms)
end
it "should raise invalid usage error by default" do
expect { subject.execute }.to raise_error(Vagrant::Errors::CLIInvalidUsage)
end
context "when three arguments are provided" do
let(:argv) { ["source", "destination", "guest"] }
before { allow(File).to receive(:file?).and_return(true) }
it "should use third argument as name of guest" do
expect(subject).to receive(:with_target_vms).with("guest", any_args)
subject.execute
end
it "should use first argument as source and second as destination" do
allow(subject).to receive(:with_target_vms) { |&block| block.call machine }
expect(communicator).to receive(:upload).with("source", "destination")
subject.execute
end
end
context "when two arguments are provided" do
let(:argv) { ["source", "ambiguous"] }
let(:active_machines) { [] }
before do
allow(File).to receive(:file?).and_return(true)
allow(iso_env).to receive(:active_machines).and_return(active_machines)
end
it "should use the the second argument as destination when not a machine name" do
allow(subject).to receive(:with_target_vms) { |&block| block.call machine }
expect(communicator).to receive(:upload).with("source", "ambiguous")
subject.execute
end
context "when active machine matches second argument" do
let(:active_machines) { [["ambiguous"]] }
it "should use second argument as guest name and generate destination" do
allow(subject).to receive(:with_target_vms).with("ambiguous", any_args) { |&block| block.call machine }
expect(communicator).to receive(:upload).with("source", "source")
subject.execute
end
end
end
context "when single argument is provided" do
let(:argv) { ["item"] }
before do
allow(File).to receive(:file?)
allow(File).to receive(:directory?)
end
it "should check if source is a file" do
expect(File).to receive(:file?).with("item").and_return(true)
subject.execute
end
it "should check if source is a directory" do
expect(File).to receive(:directory?).with("item").and_return(true)
subject.execute
end
it "should raise error if source is not a directory or file" do
expect { subject.execute }.to raise_error(Vagrant::Errors::UploadSourceMissing)
end
context "when source path ends with double quote" do
let(:argv) { [".\\item\""] }
it "should remove trailing quote" do
expect(File).to receive(:file?).with(".\\item").and_return(true)
subject.execute
end
end
context "when source path ends with single quote" do
let(:argv) { ['.\item\''] }
it "should remove trailing quote" do
expect(File).to receive(:file?).with(".\\item").and_return(true)
subject.execute
end
end
context "when source is a directory" do
before do
allow(File).to receive(:file?).with("item").and_return(false)
allow(File).to receive(:directory?).with("item").and_return(true)
allow(communicator).to receive(:upload)
allow(subject).to receive(:with_target_vms) { |&block| block.call machine }
end
it "should upload the directory" do
expect(communicator).to receive(:upload).with(/item/, anything)
subject.execute
end
it "should append separator and dot to source path for upload" do
expect(communicator).to receive(:upload).with("item/.", anything)
subject.execute
end
end
context "when source is a file" do
before do
allow(File).to receive(:file?).with("item").and_return(true)
allow(communicator).to receive(:upload)
allow(subject).to receive(:with_target_vms) { |&block| block.call machine }
allow(machine).to receive(:guest).and_return(guest)
allow(machine).to receive(:env).and_return(double("env", host: host))
allow(guest).to receive(:capability?).and_return(true)
allow(guest).to receive(:capability)
end
it "should upload the file" do
expect(communicator).to receive(:upload).with("item", anything)
subject.execute
end
it "should name destination after the source" do
expect(communicator).to receive(:upload).with("item", "item")
subject.execute
end
context "when temporary option is set" do
before { argv << "-t" }
it "should get temporary path for destination from guest" do
expect(guest).to receive(:capability).with(:create_tmp_path, any_args).and_return("TMP_PATH")
expect(communicator).to receive(:upload).with("item", "TMP_PATH")
subject.execute
end
end
context "when compress option is set" do
before do
argv << "-c"
allow(guest).to receive(:capability).with(:create_tmp_path, any_args).and_return("TMP")
allow(subject).to receive(:compress_source_zip).and_return("COMPRESS_SOURCE")
allow(subject).to receive(:compress_source_tgz).and_return("COMPRESS_SOURCE")
allow(FileUtils).to receive(:rm).with("COMPRESS_SOURCE")
end
it "should check for guest decompression" do
expect(guest).to receive(:capability?).with(:decompress_tgz).and_return(true)
subject.execute
end
it "should compress the source" do
expect(subject).to receive(:compress_source_tgz).with("item").and_return("COMPRESS_SOURCE")
subject.execute
end
it "should cleanup compressed source" do
expect(FileUtils).to receive(:rm).with("COMPRESS_SOURCE")
subject.execute
end
it "should upload the compressed source" do
expect(communicator).to receive(:upload).with("COMPRESS_SOURCE", anything)
subject.execute
end
it "should upload compressed source to temporary location" do
expect(communicator).to receive(:upload).with("COMPRESS_SOURCE", "TMP")
subject.execute
end
it "should have guest decompress file" do
expect(guest).to receive(:capability).with(:decompress_tgz, "TMP", any_args)
subject.execute
end
it "should provide destination for guest decompression of file" do
expect(guest).to receive(:capability).with(:decompress_tgz, "TMP", "item", any_args)
subject.execute
end
it "should provide the destination type for guest decompression" do
expect(guest).to receive(:capability).with(:decompress_tgz, "TMP", "item", hash_including(type: :file))
subject.execute
end
context "with compression type set to zip" do
before { argv << "-C" << "zip" }
it "should test guest for decompression capability" do
expect(guest).to receive(:capability?).with(:decompress_zip).and_return(true)
subject.execute
end
it "should compress source using zip" do
expect(subject).to receive(:compress_source_zip)
subject.execute
end
it "should have guest decompress file using zip" do
expect(guest).to receive(:capability).with(:decompress_zip, any_args)
subject.execute
end
end
end
end
end
end

View File

@ -0,0 +1,95 @@
require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/commands/winrm/command")
describe VagrantPlugins::CommandWinRM::Command do
include_context "unit"
include_context "virtualbox"
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(:host) { double("host") }
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
let(:communicator) { double("communicator") }
let(:argv) { [] }
let(:config) {
double("config",
vm: double("vm-config", communicator: communicator_name))
}
let(:communicator_name) { :winrm }
subject { described_class.new(argv, iso_env) }
before do
allow(machine).to receive(:communicate).and_return(communicator)
allow(machine).to receive(:config).and_return(config)
allow(subject).to receive(:with_target_vms) { |&block| block.call machine }
allow(communicator).to receive(:execute)
end
it "should exit successfully when no command is provided" do
expect(subject.execute).to eq(0)
end
context "with command provided" do
let(:argv){ ["-c", "dir"] }
it "should execute the command via the communicator" do
expect(communicator).to receive(:execute).with("dir", any_args)
subject.execute
end
it "should execute with default shell" do
expect(communicator).to receive(:execute).with(anything, hash_including(shell: :powershell))
subject.execute
end
it "should execute without elevated privileges" do
expect(communicator).to receive(:execute).with(anything, hash_including(elevated: false))
subject.execute
end
context "with elevated option set" do
let(:argv) { ["-c", "dir", "-e"] }
it "should execute with elevated privileges" do
expect(communicator).to receive(:execute).with(anything, hash_including(elevated: true))
subject.execute
end
end
context "with shell option set" do
let(:argv) { ["-c", "dir", "-s", "cmd"] }
it "should execute with custom shell" do
expect(communicator).to receive(:execute).with(anything, hash_including(shell: :cmd))
subject.execute
end
end
end
context "with multiple command provided" do
let(:argv) { ["-c", "dir", "-c", "dir2"] }
it "should execute multiple commands via the communicator" do
expect(communicator).to receive(:execute).with("dir", any_args)
expect(communicator).to receive(:execute).with("dir2", any_args)
subject.execute
end
end
context "with invalid communicator configured" do
let(:communicator_name) { :ssh }
it "should raise an error" do
expect { subject.execute }.to raise_error(Vagrant::Errors::WinRMInvalidCommunicator)
end
end
end

View File

@ -0,0 +1,143 @@
require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/commands/winrm_config/command")
require Vagrant.source_root.join("plugins/communicators/winrm/helper")
describe VagrantPlugins::CommandWinRMConfig::Command do
include_context "unit"
include_context "virtualbox"
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(:host) { double("host") }
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
let(:argv) { [] }
let(:winrm_info) {{
host: "testhost.vagrant.dev",
port: 1234
}}
let(:config) {
double("config",
winrm: double("winrm-config", username: "vagrant", password: "vagrant"),
rdp: rdp_config,
vm: double("vm-config", communicator: :winrm)
)
}
let(:rdp_config) { double("rdp-config", port: 9876) }
subject { described_class.new(argv, iso_env) }
before do
allow(machine).to receive(:config).and_return(config)
allow(VagrantPlugins::CommunicatorWinRM::Helper).to receive(:winrm_info).and_return(winrm_info)
allow(subject).to receive(:with_target_vms) { |&block| block.call machine }
end
describe "execute" do
it "prints out the winrm config for the given machine" do
output = ""
allow(subject).to receive(:safe_puts) do |data|
output += data if data
end
subject.execute
expect(output).to eq(<<-WINRMCONFIG)
Host #{machine.name}
HostName testhost.vagrant.dev
User vagrant
Password vagrant
Port 1234
RDPHostName testhost.vagrant.dev
RDPPort 9876
RDPUser vagrant
RDPPassword vagrant
WINRMCONFIG
end
context "with host option set" do
let(:argv) { ["--host", "my-host"]}
it "should use custom host name in config output" do
output = ""
allow(subject).to receive(:safe_puts) do |data|
output += data if data
end
subject.execute
expect(output).to eq(<<-WINRMCONFIG)
Host my-host
HostName testhost.vagrant.dev
User vagrant
Password vagrant
Port 1234
RDPHostName testhost.vagrant.dev
RDPPort 9876
RDPUser vagrant
RDPPassword vagrant
WINRMCONFIG
end
end
context "when no RDP port is configured" do
let(:rdp_config) { double("rdp-config", port: nil) }
it "should not include any RDP configuration information" do
output = ""
allow(subject).to receive(:safe_puts) do |data|
output += data if data
end
subject.execute
expect(output).not_to include("RDP")
end
end
context "when provider has rdp_info capability" do
let(:rdp_info) {
{host: "provider-host", port: 9999, username: "pvagrant", password: "pvagrant"}
}
before do
allow(machine.provider).to receive(:capability?).with(:rdp_info).and_return(true)
allow(machine.provider).to receive(:capability).with(:rdp_info).and_return(rdp_info)
end
it "should use provider RDP information" do
output = ""
allow(subject).to receive(:safe_puts) do |data|
output += data if data
end
subject.execute
expect(output).to include("RDPPort 9999")
expect(output).to include("RDPHostName provider-host")
expect(output).to include("RDPUser pvagrant")
expect(output).to include("RDPPassword pvagrant")
end
context "when provider rdp_info does not include host" do
before { rdp_info[:host] = nil }
it "should use winrm host" do
output = ""
allow(subject).to receive(:safe_puts) do |data|
output += data if data
end
subject.execute
expect(output).to include("RDPHostName testhost.vagrant.dev")
end
end
end
end
end

View File

@ -0,0 +1,127 @@
require_relative "../../../../base"
describe "VagrantPlugins::GuestBSD::Cap::FileSystem" do
let(:caps) do
VagrantPlugins::GuestBSD::Plugin
.components
.guest_capabilities[:bsd]
end
let(:machine) { double("machine", communicate: comm) }
let(:comm) { double("comm") }
before { allow(comm).to receive(:execute) }
describe ".create_tmp_path" do
let(:cap) { caps.get(:create_tmp_path) }
let(:opts) { {} }
it "should generate path on guest" do
expect(comm).to receive(:execute).with(/mktemp/)
cap.create_tmp_path(machine, opts)
end
it "should capture path generated on guest" do
expect(comm).to receive(:execute).with(/mktemp/).and_yield(:stdout, "TMP_PATH")
expect(cap.create_tmp_path(machine, opts)).to eq("TMP_PATH")
end
it "should strip newlines on path" do
expect(comm).to receive(:execute).with(/mktemp/).and_yield(:stdout, "TMP_PATH\n")
expect(cap.create_tmp_path(machine, opts)).to eq("TMP_PATH")
end
context "when type is a directory" do
before { opts[:type] = :directory }
it "should create guest path as a directory" do
expect(comm).to receive(:execute).with(/-d/)
cap.create_tmp_path(machine, opts)
end
end
end
describe ".decompress_tgz" do
let(:cap) { caps.get(:decompress_tgz) }
let(:comp) { "compressed_file" }
let(:dest) { "path/to/destination" }
let(:opts) { {} }
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
after{ cap.decompress_tgz(machine, comp, dest, opts) }
it "should create temporary directory for extraction" do
expect(cap).to receive(:create_tmp_path)
end
it "should extract file with tar" do
expect(comm).to receive(:execute).with(/tar/)
end
it "should extract file to temporary directory" do
expect(comm).to receive(:execute).with(/TMP_DIR/)
end
it "should remove compressed file from guest" do
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
end
it "should remove extraction directory from guest" do
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
end
it "should create parent directories for destination" do
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
end
context "when type is directory" do
before { opts[:type] = :directory }
it "should create destination directory" do
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
end
end
end
describe ".decompress_zip" do
let(:cap) { caps.get(:decompress_zip) }
let(:comp) { "compressed_file" }
let(:dest) { "path/to/destination" }
let(:opts) { {} }
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
after{ cap.decompress_zip(machine, comp, dest, opts) }
it "should create temporary directory for extraction" do
expect(cap).to receive(:create_tmp_path)
end
it "should extract file with zip" do
expect(comm).to receive(:execute).with(/zip/)
end
it "should extract file to temporary directory" do
expect(comm).to receive(:execute).with(/TMP_DIR/)
end
it "should remove compressed file from guest" do
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
end
it "should remove extraction directory from guest" do
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
end
it "should create parent directories for destination" do
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
end
context "when type is directory" do
before { opts[:type] = :directory }
it "should create destination directory" do
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
end
end
end
end

View File

@ -0,0 +1,127 @@
require_relative "../../../../base"
describe "VagrantPlugins::GuestLinux::Cap::FileSystem" do
let(:caps) do
VagrantPlugins::GuestLinux::Plugin
.components
.guest_capabilities[:linux]
end
let(:machine) { double("machine", communicate: comm) }
let(:comm) { double("comm") }
before { allow(comm).to receive(:execute) }
describe ".create_tmp_path" do
let(:cap) { caps.get(:create_tmp_path) }
let(:opts) { {} }
it "should generate path on guest" do
expect(comm).to receive(:execute).with(/mktemp/)
cap.create_tmp_path(machine, opts)
end
it "should capture path generated on guest" do
expect(comm).to receive(:execute).with(/mktemp/).and_yield(:stdout, "TMP_PATH")
expect(cap.create_tmp_path(machine, opts)).to eq("TMP_PATH")
end
it "should strip newlines on path" do
expect(comm).to receive(:execute).with(/mktemp/).and_yield(:stdout, "TMP_PATH\n")
expect(cap.create_tmp_path(machine, opts)).to eq("TMP_PATH")
end
context "when type is a directory" do
before { opts[:type] = :directory }
it "should create guest path as a directory" do
expect(comm).to receive(:execute).with(/-d/)
cap.create_tmp_path(machine, opts)
end
end
end
describe ".decompress_tgz" do
let(:cap) { caps.get(:decompress_tgz) }
let(:comp) { "compressed_file" }
let(:dest) { "path/to/destination" }
let(:opts) { {} }
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
after{ cap.decompress_tgz(machine, comp, dest, opts) }
it "should create temporary directory for extraction" do
expect(cap).to receive(:create_tmp_path)
end
it "should extract file with tar" do
expect(comm).to receive(:execute).with(/tar/)
end
it "should extract file to temporary directory" do
expect(comm).to receive(:execute).with(/TMP_DIR/)
end
it "should remove compressed file from guest" do
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
end
it "should remove extraction directory from guest" do
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
end
it "should create parent directories for destination" do
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
end
context "when type is directory" do
before { opts[:type] = :directory }
it "should create destination directory" do
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
end
end
end
describe ".decompress_zip" do
let(:cap) { caps.get(:decompress_zip) }
let(:comp) { "compressed_file" }
let(:dest) { "path/to/destination" }
let(:opts) { {} }
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
after{ cap.decompress_zip(machine, comp, dest, opts) }
it "should create temporary directory for extraction" do
expect(cap).to receive(:create_tmp_path)
end
it "should extract file with zip" do
expect(comm).to receive(:execute).with(/zip/)
end
it "should extract file to temporary directory" do
expect(comm).to receive(:execute).with(/TMP_DIR/)
end
it "should remove compressed file from guest" do
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
end
it "should remove extraction directory from guest" do
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
end
it "should create parent directories for destination" do
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
end
context "when type is directory" do
before { opts[:type] = :directory }
it "should create destination directory" do
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
end
end
end
end

View File

@ -0,0 +1,127 @@
require_relative "../../../../base"
describe "VagrantPlugins::GuestSolaris::Cap::FileSystem" do
let(:caps) do
VagrantPlugins::GuestSolaris::Plugin
.components
.guest_capabilities[:solaris]
end
let(:machine) { double("machine", communicate: comm) }
let(:comm) { double("comm") }
before { allow(comm).to receive(:execute) }
describe ".create_tmp_path" do
let(:cap) { caps.get(:create_tmp_path) }
let(:opts) { {} }
it "should generate path on guest" do
expect(comm).to receive(:execute).with(/mktemp/)
cap.create_tmp_path(machine, opts)
end
it "should capture path generated on guest" do
expect(comm).to receive(:execute).with(/mktemp/).and_yield(:stdout, "TMP_PATH")
expect(cap.create_tmp_path(machine, opts)).to eq("TMP_PATH")
end
it "should strip newlines on path" do
expect(comm).to receive(:execute).with(/mktemp/).and_yield(:stdout, "TMP_PATH\n")
expect(cap.create_tmp_path(machine, opts)).to eq("TMP_PATH")
end
context "when type is a directory" do
before { opts[:type] = :directory }
it "should create guest path as a directory" do
expect(comm).to receive(:execute).with(/-d/)
cap.create_tmp_path(machine, opts)
end
end
end
describe ".decompress_tgz" do
let(:cap) { caps.get(:decompress_tgz) }
let(:comp) { "compressed_file" }
let(:dest) { "path/to/destination" }
let(:opts) { {} }
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
after{ cap.decompress_tgz(machine, comp, dest, opts) }
it "should create temporary directory for extraction" do
expect(cap).to receive(:create_tmp_path)
end
it "should extract file with tar" do
expect(comm).to receive(:execute).with(/tar/)
end
it "should extract file to temporary directory" do
expect(comm).to receive(:execute).with(/TMP_DIR/)
end
it "should remove compressed file from guest" do
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
end
it "should remove extraction directory from guest" do
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
end
it "should create parent directories for destination" do
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
end
context "when type is directory" do
before { opts[:type] = :directory }
it "should create destination directory" do
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
end
end
end
describe ".decompress_zip" do
let(:cap) { caps.get(:decompress_zip) }
let(:comp) { "compressed_file" }
let(:dest) { "path/to/destination" }
let(:opts) { {} }
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
after{ cap.decompress_zip(machine, comp, dest, opts) }
it "should create temporary directory for extraction" do
expect(cap).to receive(:create_tmp_path)
end
it "should extract file with zip" do
expect(comm).to receive(:execute).with(/zip/)
end
it "should extract file to temporary directory" do
expect(comm).to receive(:execute).with(/TMP_DIR/)
end
it "should remove compressed file from guest" do
expect(comm).to receive(:execute).with(/rm .*#{comp}/)
end
it "should remove extraction directory from guest" do
expect(comm).to receive(:execute).with(/rm .*TMP_DIR/)
end
it "should create parent directories for destination" do
expect(comm).to receive(:execute).with(/mkdir -p .*to'/)
end
context "when type is directory" do
before { opts[:type] = :directory }
it "should create destination directory" do
expect(comm).to receive(:execute).with(/mkdir -p .*destination'/)
end
end
end
end

View File

@ -0,0 +1,85 @@
require_relative "../../../../base"
describe "VagrantPlugins::GuestWindows::Cap::FileSystem" do
let(:caps) do
VagrantPlugins::GuestWindows::Plugin
.components
.guest_capabilities[:windows]
end
let(:machine) { double("machine", communicate: comm) }
let(:comm) { double("comm") }
before { allow(comm).to receive(:execute) }
describe ".create_tmp_path" do
let(:cap) { caps.get(:create_tmp_path) }
let(:opts) { {} }
it "should generate path on guest" do
expect(comm).to receive(:execute).with(/GetRandomFileName/, any_args)
cap.create_tmp_path(machine, opts)
end
it "should capture path generated on guest" do
expect(comm).to receive(:execute).with(/Write-Output/, any_args).and_yield(:stdout, "TMP_PATH")
expect(cap.create_tmp_path(machine, opts)).to eq("TMP_PATH")
end
it "should strip newlines on path" do
expect(comm).to receive(:execute).with(/Write-Output/, any_args).and_yield(:stdout, "TMP_PATH\r\n")
expect(cap.create_tmp_path(machine, opts)).to eq("TMP_PATH")
end
context "when type is a directory" do
before { opts[:type] = :directory }
it "should create guest path as a directory" do
expect(comm).to receive(:execute).with(/CreateDirectory/, any_args)
cap.create_tmp_path(machine, opts)
end
end
end
describe ".decompress_zip" do
let(:cap) { caps.get(:decompress_zip) }
let(:comp) { "compressed_file" }
let(:dest) { "path/to/destination" }
let(:opts) { {} }
before { allow(cap).to receive(:create_tmp_path).and_return("TMP_DIR") }
after{ cap.decompress_zip(machine, comp, dest, opts) }
it "should create temporary directory for extraction" do
expect(cap).to receive(:create_tmp_path)
end
it "should extract file with zip" do
expect(comm).to receive(:execute).with(/copyhere/, any_args)
end
it "should extract file to temporary directory" do
expect(comm).to receive(:execute).with(/TMP_DIR/, any_args)
end
it "should remove compressed file from guest" do
expect(comm).to receive(:execute).with(/Remove-Item .*#{comp}/, any_args)
end
it "should remove extraction directory from guest" do
expect(comm).to receive(:execute).with(/Remove-Item .*TMP_DIR/, any_args)
end
it "should create parent directories for destination" do
expect(comm).to receive(:execute).with(/New-Item .*Directory .*to\\"/, any_args)
end
context "when type is directory" do
before { opts[:type] = :directory }
it "should create destination directory" do
expect(comm).to receive(:execute).with(/New-Item .*Directory .*destination"/, any_args)
end
end
end
end

View File

@ -27,6 +27,7 @@ Gem::Specification.new do |s|
s.add_dependency "net-scp", "~> 1.2.0" s.add_dependency "net-scp", "~> 1.2.0"
s.add_dependency "rb-kqueue", "~> 0.2.0" s.add_dependency "rb-kqueue", "~> 0.2.0"
s.add_dependency "rest-client", ">= 1.6.0", "< 3.0" s.add_dependency "rest-client", ">= 1.6.0", "< 3.0"
s.add_dependency "rubyzip", "~> 1.2.2"
s.add_dependency "wdm", "~> 0.1.0" s.add_dependency "wdm", "~> 0.1.0"
s.add_dependency "winrm", "~> 2.1" s.add_dependency "winrm", "~> 2.1"
s.add_dependency "winrm-fs", "~> 1.0" s.add_dependency "winrm-fs", "~> 1.0"

View File

@ -0,0 +1,30 @@
---
layout: "docs"
page_title: "vagrant upload - Command-Line Interface"
sidebar_current: "cli-upload"
description: |-
The "vagrant upload" command is used to upload files from the host
to a guest machine.
---
# Upload
**Command: `vagrant upload source [destination] [name|id]`**
This command uploads files and directories from the host to the guest
machine.
## Options
* `destination` - Path on the guest machine to upload file or directory.
* `source` - Path to file or diretory on host to upload to guest machine.
* `--compress` - Compress the file or directory before uploading to guest machine.
* `--compression-type type` - Type of compression to use when compressing
file or directory for upload. Defaults to `zip` for Windows guests and
`tgz` for non-Windows guests. Valid values: `tgz`, `zip`.
* `--temporary` - Create a temporary location on the guest machine and upload
files to that location.

View File

@ -0,0 +1,26 @@
---
layout: "docs"
page_title: "vagrant winrm - Command-Line Interface"
sidebar_current: "cli-winrm"
description: |-
The "vagrant winrm" command is used execute commands on the remote
machine via WinRM
---
# WinRM
**Command: `vagrant winrm [name|id]`**
Executes the provided command(s) on the guest machine using the
WinRM communicator. Commands are provided with the `--command`
option and multiple `--command` flags may be provided for
executing multiple commands. This command requires the guest
machine to be configured with the WinRM communicator.
## Options
* `--command COMMAND` - Command to execute.
* `--elevated` - Run command(s) with elevated credentials.
* `--shell (cmd|powershell)` - Shell to execute commands. Defaults to `powershell`.

View File

@ -0,0 +1,20 @@
---
layout: "docs"
page_title: "vagrant winrm-config - Command-Line Interface"
sidebar_current: "cli-winrm_config"
description: |-
The "vagrant winrm-config" command is used to output the WinRM configuration
used to connect to the guest machine.
---
# WinRM Config
**Command: `vagrant winrm-config [name|id]`**
This will output the WinRM configuration used for connecting to
the guest machine. It requires that the WinRM communicator is in
use for the guest machine.
## Options
* `--host NAME` - Name of the host for the outputted configuration.