winrm-fs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ $p = $ExecutionContext.SessionState.Path
2
+ $path = $p.GetUnresolvedProviderPathFromPSPath("<%= path %>")
3
+
4
+ if (Test-Path $path -PathType Leaf) {
5
+ $cryptoProv = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
6
+ $file = [System.IO.File]::Open($path,
7
+ [System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
8
+ $md5 = ([System.BitConverter]::ToString($cryptoProv.ComputeHash($file)))
9
+ $md5 = $md5.Replace("-","").ToLower()
10
+ $file.Close()
11
+
12
+ Write-Host $md5
13
+ }
@@ -0,0 +1,6 @@
1
+ $p = $ExecutionContext.SessionState.Path
2
+ $path = $p.GetUnresolvedProviderPathFromPSPath("<%= path %>")
3
+ if (!(Test-Path $path)) {
4
+ New-Item -ItemType Directory -Force -Path $path | Out-Null
5
+ }
6
+ exit 0
@@ -0,0 +1,36 @@
1
+ $path = $ExecutionContext.SessionState.Path
2
+ $tempFile = $path.GetUnresolvedProviderPathFromPSPath("<%= src %>")
3
+ $dest = $path.GetUnresolvedProviderPathFromPSPath("<%= dest %>")
4
+
5
+ function Decode-File($encodedFile, $decodedFile) {
6
+ if (Test-Path $encodedFile) {
7
+ $base64Content = Get-Content $encodedFile
8
+ }
9
+ if ($base64Content -eq $null) {
10
+ New-Item -ItemType file -Force $decodedFile | Out-Null
11
+ }
12
+ else {
13
+ $bytes = [System.Convert]::FromBase64String($base64Content)
14
+ [System.IO.File]::WriteAllBytes($decodedFile, $bytes) | Out-Null
15
+ }
16
+ }
17
+
18
+ function Ensure-Dir-Exists($path) {
19
+ # ensure the destination directory exists
20
+ if (!(Test-Path $path)) {
21
+ New-Item -ItemType Directory -Force -Path $path | Out-Null
22
+ }
23
+ }
24
+
25
+ if ([System.IO.Path]::GetExtension($tempFile) -eq '.zip') {
26
+ Ensure-Dir-Exists $dest
27
+ Decode-File $tempFile $tempFile
28
+ $shellApplication = New-Object -com shell.application
29
+ $zipPackage = $shellApplication.NameSpace($tempFile)
30
+ $destinationFolder = $shellApplication.NameSpace($dest)
31
+ $destinationFolder.CopyHere($zipPackage.Items(), 0x10) | Out-Null
32
+ }
33
+ else {
34
+ Ensure-Dir-Exists ([System.IO.Path]::GetDirectoryName($dest))
35
+ Decode-File $tempFile $dest
36
+ }
@@ -0,0 +1,6 @@
1
+ $p = $ExecutionContext.SessionState.Path
2
+ $path = $p.GetUnresolvedProviderPathFromPSPath("<%= path %>")
3
+ if (Test-Path $path) {
4
+ Remove-Item $path -Force -Recurse
5
+ }
6
+ exit 0
@@ -0,0 +1,7 @@
1
+ $p = $ExecutionContext.SessionState.Path
2
+ $path = $p.GetUnresolvedProviderPathFromPSPath("<%= path %>")
3
+ if (Test-Path $path -PathType Leaf) {
4
+ [System.convert]::ToBase64String([System.IO.File]::ReadAllBytes($path))
5
+ exit 0
6
+ }
7
+ exit 1
@@ -0,0 +1,8 @@
1
+ $p = $ExecutionContext.SessionState.Path
2
+ $path = $p.GetUnresolvedProviderPathFromPSPath("<%= path %>")
3
+ if (Test-Path $path) {
4
+ exit 0
5
+ }
6
+ else {
7
+ exit 1
8
+ }
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright 2015 Shawn Neal <sneal@sneal.net>
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'erubis'
18
+
19
+ module WinRM
20
+ module FS
21
+ # PS1 scripts
22
+ module Scripts
23
+ def self.render(template, context)
24
+ template_path = File.expand_path(
25
+ "#{File.dirname(__FILE__)}/#{template}.ps1.erb")
26
+ template = File.read(template_path)
27
+ Erubis::Eruby.new(template).result(context)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ auth_type: plaintext
2
+ endpoint: "http://localhost:55985/wsman"
3
+ options:
4
+ user: vagrant
5
+ pass: vagrant
@@ -0,0 +1,140 @@
1
+ # encoding: UTF-8
2
+ describe WinRM::FS::FileManager, integration: true do
3
+ let(:dest_dir) { File.join(subject.temp_dir, "winrm_#{rand(2**16)}") }
4
+ let(:temp_upload_dir) { '$env:TEMP/winrm-upload' }
5
+ let(:src_dir) { File.expand_path(File.dirname(__FILE__)) }
6
+ let(:service) { winrm_connection }
7
+
8
+ subject { WinRM::FS::FileManager.new(service) }
9
+
10
+ before(:each) do
11
+ expect(subject.delete(dest_dir)).to be true
12
+ expect(subject.delete(temp_upload_dir)).to be true
13
+ end
14
+
15
+ context 'exists?' do
16
+ it 'should exist' do
17
+ expect(subject.exists?('c:/windows')).to be true
18
+ expect(subject.exists?('c:/foobar')).to be false
19
+ end
20
+ end
21
+
22
+ context 'create and delete dir' do
23
+ it 'should create the directory recursively' do
24
+ subdir = File.join(dest_dir, 'subdir1', 'subdir2')
25
+ expect(subject.create_dir(subdir)).to be true
26
+ expect(subject.exists?(subdir)).to be true
27
+ expect(subject.create_dir(subdir)).to be true
28
+ expect(subject.delete(subdir)).to be true
29
+ expect(subject.exists?(subdir)).to be false
30
+ end
31
+ end
32
+
33
+ context 'temp_dir' do
34
+ it 'should return the remote users temp dir' do
35
+ expect(subject.temp_dir).to match(%r{C:/Users/\w+/AppData/Local/Temp})
36
+ end
37
+ end
38
+
39
+ context 'upload file' do
40
+ let(:src_file) { __FILE__ }
41
+ let(:dest_file) { File.join(dest_dir, File.basename(src_file)) }
42
+
43
+ before(:each) do
44
+ expect(subject.delete(dest_dir)).to be true
45
+ end
46
+
47
+ it 'should upload the file to the specified file' do
48
+ subject.upload(src_file, dest_file)
49
+ expect(subject).to have_created(dest_file).with_content(src_file)
50
+ end
51
+
52
+ it 'should upload the file to the specified directory' do
53
+ subject.upload(src_file, dest_dir)
54
+ expect(subject).to have_created(dest_file).with_content(src_file)
55
+ end
56
+
57
+ it 'should upload the file to the specified directory with env var' do
58
+ subject.upload(src_file, '$env:Temp')
59
+ expected_dest_file = File.join(subject.temp_dir, File.basename(src_file))
60
+ expect(subject).to have_created(expected_dest_file).with_content(src_file)
61
+ end
62
+
63
+ it 'should upload the file to the specified nested directory' do
64
+ dest_sub_dir = File.join(dest_dir, 'subdir')
65
+ dest_sub_dir_file = File.join(dest_sub_dir, File.basename(src_file))
66
+ subject.upload(src_file, dest_sub_dir)
67
+ expect(subject).to have_created(dest_sub_dir_file).with_content(src_file)
68
+ end
69
+
70
+ it 'yields progress data' do
71
+ total = subject.upload(src_file, dest_file) do \
72
+ |bytes_copied, total_bytes, local_path, remote_path|
73
+ expect(total_bytes).to be > 0
74
+ expect(bytes_copied).to eq(total_bytes)
75
+ expect(local_path).to eq(src_file)
76
+ expect(remote_path).to eq(dest_file)
77
+ end
78
+ expect(total).to be > 0
79
+ end
80
+
81
+ it 'should not upload the file when content matches' do
82
+ subject.upload(src_file, dest_dir)
83
+ bytes_uploaded = subject.upload(src_file, dest_dir)
84
+ expect(bytes_uploaded).to eq 0
85
+ end
86
+
87
+ it 'should upload file when content differs' do
88
+ another_src_file = File.join(src_dir, 'matchers.rb')
89
+ subject.upload(another_src_file, dest_file)
90
+ bytes_uploaded = subject.upload(src_file, dest_file)
91
+ expect(bytes_uploaded).to be > 0
92
+ end
93
+
94
+ it 'raises WinRMUploadError when a bad source path is specified' do
95
+ expect { subject.upload('c:/some/non-existant/path/foo', dest_file) }.to raise_error
96
+ end
97
+ end
98
+
99
+ context 'upload empty file' do
100
+ let(:src_file) { __FILE__ }
101
+ let(:empty_src_file) { Tempfile.new('empty').path }
102
+ let(:dest_file) { File.join(dest_dir, 'emptyfile.txt') }
103
+
104
+ it 'creates a new empty file' do
105
+ expect(subject.upload(empty_src_file, dest_file)).to be 0
106
+ expect(subject).to have_created(dest_file).with_content('')
107
+ end
108
+
109
+ it 'overwrites an existing file' do
110
+ expect(subject.upload(src_file, dest_file)).to be > 0
111
+ expect(subject.upload(empty_src_file, dest_file)).to be 0
112
+ expect(subject).to have_created(dest_file).with_content('')
113
+ end
114
+ end
115
+
116
+ context 'upload directory' do
117
+ it 'copies the entire directory' do
118
+ bytes_uploaded = subject.upload(src_dir, dest_dir)
119
+ expect(bytes_uploaded).to be > 0
120
+ Dir.glob(src_dir + '/*.rb').each do |host_file|
121
+ host_file_rel = host_file[src_dir.length..-1]
122
+ remote_file = File.join(dest_dir, host_file_rel)
123
+ expect(subject).to have_created(remote_file).with_content(host_file)
124
+ end
125
+ end
126
+
127
+ it 'does not copy the directory when content is the same' do
128
+ subject.upload(src_dir, dest_dir)
129
+ bytes_uploaded = subject.upload(src_dir, dest_dir)
130
+ expect(bytes_uploaded).to eq 0
131
+ end
132
+
133
+ it 'copies the directory when content differs' do
134
+ subject.upload(src_dir, dest_dir)
135
+ another_dir = File.dirname(src_dir)
136
+ bytes_uploaded = subject.upload(another_dir, dest_dir)
137
+ expect(bytes_uploaded).to be > 0
138
+ end
139
+ end
140
+ end
data/spec/matchers.rb ADDED
@@ -0,0 +1,54 @@
1
+ # encoding: UTF-8
2
+ require 'rspec/expectations'
3
+
4
+ RSpec::Matchers.define :have_created do |remote_file|
5
+ match do |file_manager|
6
+ if @expected_content
7
+ downloaded_file = Tempfile.new('downloaded')
8
+ downloaded_file.close
9
+
10
+ subject.download(remote_file, downloaded_file.path)
11
+ @actual_content = File.read(downloaded_file.path)
12
+ downloaded_file.delete
13
+
14
+ file_manager.exists?(remote_file) && \
15
+ @actual_content == @expected_content
16
+ else
17
+ file_manager.exists?(remote_file)
18
+ end
19
+ end
20
+ chain :with_content do |expected_content|
21
+ expected_content = File.read(expected_content) if File.file?(expected_content)
22
+ @expected_content = expected_content
23
+ end
24
+ failure_message do
25
+ if @expected_content
26
+ <<-EOH
27
+ Expected file '#{remote_file}' to exist with content:
28
+
29
+ #{@expected_content}
30
+
31
+ but instead got content:
32
+
33
+ #{@actual_content}
34
+ EOH
35
+ else
36
+ "Expected file '#{remote_file}' to exist"
37
+ end
38
+ end
39
+ end
40
+
41
+ RSpec::Matchers.define :contain_zip_entries do |zip_entries|
42
+ match do |temp_zip_file|
43
+ zip_entries = [zip_entries] if zip_entries.is_a? String
44
+ zip_file = Zip::File.open(temp_zip_file.path)
45
+ @missing_entries = []
46
+ zip_entries.each do |entry|
47
+ @missing_entries << entry unless zip_file.find_entry(entry)
48
+ end
49
+ @missing_entries.empty?
50
+ end
51
+ failure_message do |temp_zip_file|
52
+ "Expected #{temp_zip_file.path} to contain zip entries: #{@missing_entries}"
53
+ end
54
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require 'winrm-fs'
5
+ require 'json'
6
+ require_relative 'matchers'
7
+
8
+ # Creates a WinRM connection for integration tests
9
+ module ConnectionHelper
10
+ def winrm_connection
11
+ config = symbolize_keys(YAML.load(File.read(winrm_config_path)))
12
+ config[:options].merge!(basic_auth_only: true) unless config[:auth_type].eql? :kerberos
13
+ winrm = WinRM::WinRMWebService.new(
14
+ config[:endpoint], config[:auth_type].to_sym, config[:options])
15
+ winrm
16
+ end
17
+
18
+ def winrm_config_path
19
+ # Copy config-example.yml to config.yml and edit for your local configuration
20
+ path = File.expand_path("#{File.dirname(__FILE__)}/config.yml")
21
+ unless File.exist?(path)
22
+ # user hasn't done this, so use sane defaults for unit tests
23
+ path = File.expand_path("#{File.dirname(__FILE__)}/config-example.yml")
24
+ end
25
+ path
26
+ end
27
+
28
+ # rubocop:disable Metrics/MethodLength
29
+ def symbolize_keys(hash)
30
+ hash.each_with_object({}) do |(key, value), result|
31
+ new_key = case key
32
+ when String then key.to_sym
33
+ else key
34
+ end
35
+ new_value = case value
36
+ when Hash then symbolize_keys(value)
37
+ else value
38
+ end
39
+ result[new_key] = new_value
40
+ result
41
+ end
42
+ end
43
+ # rubocop:enable Metrics/MethodLength
44
+ end
45
+
46
+ RSpec.configure do |config|
47
+ config.include(ConnectionHelper)
48
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: UTF-8
2
+ require 'zip'
3
+ require_relative '../lib/winrm-fs/core/temp_zip_file'
4
+
5
+ describe WinRM::FS::Core::TempZipFile, integration: true do
6
+ let(:src_dir) { File.expand_path('../lib/winrm-fs', File.dirname(__FILE__)) }
7
+ let(:src_file) { __FILE__ }
8
+
9
+ subject { WinRM::FS::Core::TempZipFile.new }
10
+ after(:each) { subject.delete }
11
+
12
+ context 'temp file creation' do
13
+ it 'should create a temp file on disk' do
14
+ expect(File.exist?(subject.path)).to be true
15
+ subject.delete
16
+ expect(File.exist?(subject.path)).to be false
17
+ end
18
+ end
19
+
20
+ context 'add_file' do
21
+ it 'should raise error when file doesn not exist' do
22
+ expect { subject.add_file('/etc/foo/does/not/exist') }.to \
23
+ raise_error('/etc/foo/does/not/exist isn\'t a file')
24
+ end
25
+
26
+ it 'should raise error when file is a directory' do
27
+ dir = File.dirname(subject.path)
28
+ expect { subject.add_file(dir) }.to \
29
+ raise_error("#{dir} isn\'t a file")
30
+ end
31
+
32
+ it 'should add a file to the zip' do
33
+ subject.add_file(src_file)
34
+ expect(subject).to contain_zip_entries(File.basename(src_file))
35
+ end
36
+ end
37
+
38
+ context 'add_directory' do
39
+ it 'should raise error when directory does not exist' do
40
+ expect { subject.add_directory('/etc/does/not/exist') }.to \
41
+ raise_error('/etc/does/not/exist isn\'t a directory')
42
+ end
43
+
44
+ it 'should raise error when directory is a file' do
45
+ expect { subject.add_directory(subject.path) }.to \
46
+ raise_error("#{subject.path} isn\'t a directory")
47
+ end
48
+
49
+ it 'should add all files in directory to the zip recursively' do
50
+ subject.add_directory(src_dir)
51
+ expect(subject).to contain_zip_entries(['exceptions.rb', 'core/temp_zip_file.rb'])
52
+ end
53
+ end
54
+
55
+ context 'add' do
56
+ it 'should add all files when given a directory' do
57
+ subject.add(src_dir)
58
+ expect(subject).to contain_zip_entries(['exceptions.rb', 'core/temp_zip_file.rb'])
59
+ end
60
+
61
+ it 'should add a file when given only a file' do
62
+ subject.add(src_file)
63
+ expect(subject).to contain_zip_entries(File.basename(src_file))
64
+ end
65
+
66
+ it 'should raise error when given a non-path' do
67
+ expect { subject.add('garbage') }.to \
68
+ raise_error("garbage doesn't exist")
69
+ end
70
+ end
71
+ end
data/winrm-fs.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # encoding: UTF-8
2
+ require 'date'
3
+
4
+ version = File.read(File.expand_path('../VERSION', __FILE__)).strip
5
+
6
+ Gem::Specification.new do |s|
7
+ s.platform = Gem::Platform::RUBY
8
+ s.name = 'winrm-fs'
9
+ s.version = version
10
+ s.date = Date.today.to_s
11
+
12
+ s.author = ['Shawn Neal', 'Matt Wrock']
13
+ s.email = ['sneal@sneal.net', 'matt@mattwrock.com']
14
+ s.homepage = 'http://github.com/WinRb/winrm-fs'
15
+
16
+ s.summary = 'WinRM File System'
17
+ s.description = <<-EOF
18
+ Ruby library for file system operations via Windows Remote Management
19
+ EOF
20
+
21
+ s.files = `git ls-files`.split(/\n/)
22
+ s.require_path = 'lib'
23
+ s.rdoc_options = %w(-x test/ -x examples/)
24
+ s.extra_rdoc_files = %w(README.md LICENSE)
25
+
26
+ s.bindir = 'bin'
27
+ s.executables = ['rwinrmcp']
28
+ s.required_ruby_version = '>= 1.9.0'
29
+ s.add_runtime_dependency 'erubis', '~> 2.7'
30
+ s.add_runtime_dependency 'logging', '~> 1.6', '>= 1.6.1'
31
+ s.add_runtime_dependency 'rubyzip', '~> 1.1'
32
+ s.add_runtime_dependency 'winrm', '~> 1.3.0'
33
+ s.add_development_dependency 'rspec', '~> 3.0.0'
34
+ s.add_development_dependency 'rake', '~> 10.3.2'
35
+ s.add_development_dependency 'rubocop', '~> 0.28.0'
36
+ end