vagrant-unbundled 2.0.0.1 → 2.0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/CHANGELOG.md +34 -0
- data/Gemfile.lock +10 -10
- data/README.md +2 -2
- data/contrib/sudoers/linux-suse +6 -7
- data/lib/vagrant/plugin/v2/command.rb +3 -0
- data/lib/vagrant/plugin/v2/communicator.rb +1 -1
- data/lib/vagrant/registry.rb +1 -1
- data/lib/vagrant/util/downloader.rb +1 -2
- data/lib/vagrant/util/is_port_open.rb +2 -1
- data/lib/vagrant/util/keypair.rb +1 -1
- data/lib/vagrant/util/platform.rb +39 -23
- data/plugins/commands/destroy/command.rb +31 -10
- data/plugins/communicators/ssh/communicator.rb +1 -0
- data/plugins/communicators/winrm/helper.rb +6 -1
- data/plugins/guests/solaris11/cap/change_host_name.rb +0 -2
- data/plugins/guests/solaris11/cap/configure_networks.rb +1 -7
- data/plugins/guests/solaris11/plugin.rb +5 -35
- data/plugins/guests/windows/cap/public_key.rb +2 -0
- data/plugins/guests/windows/guest_network.rb +3 -3
- data/plugins/guests/windows/scripts/reboot_detect.ps1 +5 -0
- data/plugins/providers/docker/driver.rb +1 -1
- data/plugins/providers/docker/executor/local.rb +4 -0
- data/plugins/providers/docker/executor/vagrant.rb +4 -0
- data/plugins/providers/hyperv/scripts/import_vm_vmcx.ps1 +1 -1
- data/plugins/providers/virtualbox/driver/meta.rb +1 -0
- data/plugins/providers/virtualbox/driver/version_5_2.rb +16 -0
- data/plugins/providers/virtualbox/plugin.rb +1 -0
- data/plugins/providers/virtualbox/synced_folder.rb +1 -1
- data/plugins/provisioners/chef/provisioner/chef_client.rb +30 -23
- data/plugins/provisioners/chef/provisioner/chef_solo.rb +26 -19
- data/plugins/provisioners/chef/provisioner/chef_zero.rb +29 -22
- data/plugins/provisioners/puppet/provisioner/puppet.rb +23 -4
- data/plugins/provisioners/salt/bootstrap-salt.ps1 +15 -3
- data/plugins/provisioners/salt/bootstrap-salt.sh +2 -0
- data/plugins/provisioners/salt/config.rb +11 -0
- data/plugins/provisioners/salt/provisioner.rb +10 -7
- data/plugins/provisioners/shell/provisioner.rb +1 -1
- data/templates/locales/en.yml +5 -0
- data/test/unit/base.rb +2 -0
- data/test/unit/plugins/commands/destroy/command_test.rb +155 -0
- data/test/unit/plugins/communicators/winrm/helper_test.rb +33 -0
- data/test/unit/plugins/guests/solaris11/cap/change_host_name_test.rb +36 -0
- data/test/unit/plugins/guests/solaris11/cap/configure_networks_test.rb +56 -0
- data/test/unit/plugins/providers/virtualbox/synced_folder_test.rb +26 -0
- data/test/unit/plugins/provisioners/salt/config_test.rb +42 -0
- data/test/unit/plugins/provisioners/salt/provisioner_test.rb +16 -1
- data/test/unit/plugins/provisioners/shell/config_test.rb +3 -3
- data/test/unit/plugins/pushes/local-exec/config_test.rb +2 -2
- data/test/unit/vagrant/util/downloader_test.rb +28 -0
- data/test/unit/vagrant/util/platform_test.rb +58 -0
- data/vagrant.gemspec +1 -1
- data/vendor/bundle/ruby/2.4.0/bin/rwinrmcp +5 -0
- data/vendor/bundle/ruby/2.4.0/bin/vagrant +5 -0
- data/vendor/bundle/ruby/2.4.0/bin/vagrant-spec +5 -0
- data/vendor/bundle/ruby/2.4.0/bundler/gems/vagrant-spec-af86757912f7/vagrant-spec.gemspec +3 -3
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/CHANGELOG.md +216 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/Gemfile +32 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/LICENSE.txt +202 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/README.md +121 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/Rakefile +32 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/data/unicode.data +0 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/idna/native.rb +59 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/idna/pure.rb +677 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/idna.rb +25 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/template.rb +1065 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/uri.rb +2492 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/version.rb +30 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable.rb +2 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/idna_spec.rb +298 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/net_http_compat_spec.rb +28 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/rack_mount_compat_spec.rb +104 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/security_spec.rb +57 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/template_spec.rb +1419 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/uri_spec.rb +6468 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/spec_helper.rb +21 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/clobber.rake +2 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/gem.rake +91 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/git.rake +45 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/metrics.rake +22 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/rspec.rake +21 -0
- data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/yard.rake +27 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/.gitignore +15 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/.rspec +1 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/.travis.yml +13 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/.yardopts +1 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/Gemfile +6 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/LICENSE +19 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/README.md +265 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/Rakefile +13 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/changelog.md +72 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/hashdiff.gemspec +25 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/diff.rb +232 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/lcs.rb +69 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/linear_compare_array.rb +155 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/patch.rb +88 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/util.rb +146 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/version.rb +3 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff.rb +6 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/best_diff_spec.rb +74 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/diff_array_spec.rb +60 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/diff_spec.rb +339 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/lcs_spec.rb +75 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/linear_compare_array_spec.rb +48 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/patch_spec.rb +183 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/util_spec.rb +78 -0
- data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/spec_helper.rb +13 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/CHANGELOG.md +250 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/CONTRIBUTING.md +46 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/LICENSE.md +20 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/README.md +122 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapter.rb +49 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapter_error.rb +15 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/gson.rb +20 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/jr_jackson.rb +25 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/json_common.rb +23 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/json_gem.rb +11 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/json_pure.rb +11 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/nsjsonserialization.rb +32 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/oj.rb +25 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/ok_json.rb +23 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/yajl.rb +19 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/convertible_hash_keys.rb +43 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/options.rb +39 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/options_cache.rb +29 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/parse_error.rb +17 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/vendor/okjson.rb +606 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/version.rb +17 -0
- data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json.rb +161 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.gitignore +11 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.rubocop.yml +32 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.rubocop_defaults.yml +177 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.travis.yml +24 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.yardopts +1 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/2.0-Upgrade.md +52 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/CHANGELOG.md +330 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/Gemfile +10 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/LICENSE.txt +22 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/README.md +202 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/Rakefile +49 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/bin/console +14 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/data/list.txt +12288 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/domain.rb +235 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/errors.rb +39 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/list.rb +243 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/rule.rb +348 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/version.rb +10 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix.rb +175 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/public_suffix.gemspec +25 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/.empty +2 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/acceptance_test.rb +127 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_find.rb +66 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_find_all.rb +102 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_names.rb +91 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_select.rb +26 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_select_incremental.rb +25 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_valid.rb +101 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/domain_profiler.rb +12 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/find_profiler.rb +12 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/find_profiler_jp.rb +12 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/initialization_profiler.rb +11 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/list_profsize.rb +11 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/object_binsize.rb +57 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/psl_test.rb +49 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/test_helper.rb +13 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/tests.txt +98 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/domain_test.rb +104 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/errors_test.rb +23 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/list_test.rb +239 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/public_suffix_test.rb +186 -0
- data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/rule_test.rb +220 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/.gemtest +0 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/.gitignore +34 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/.rspec-tm +2 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/.travis.yml +24 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/CHANGELOG.md +1460 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/Gemfile +9 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/LICENSE +20 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/README.md +1045 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/Rakefile +30 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/api.rb +97 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/assertion_failure.rb +11 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/callback_registry.rb +35 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/config.rb +18 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/cucumber.rb +10 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/deprecation.rb +9 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/errors.rb +17 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/curb_adapter.rb +337 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +228 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/excon_adapter.rb +162 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/client.rb +14 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/request.rb +10 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/response.rb +43 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/streamer.rb +25 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/httpclient_adapter.rb +240 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/manticore_adapter.rb +127 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/net_http.rb +362 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/net_http_response.rb +34 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/patron_adapter.rb +130 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +174 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/matchers/hash_including_matcher.rb +36 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/minitest.rb +41 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rack_response.rb +69 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_body_diff.rb +64 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_execution_verifier.rb +78 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_pattern.rb +343 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_registry.rb +35 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_signature.rb +54 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_signature_snippet.rb +61 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_stub.rb +100 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/response.rb +153 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/responses_sequence.rb +40 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rspec/matchers/request_pattern_matcher.rb +78 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rspec/matchers/webmock_matcher.rb +52 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rspec/matchers.rb +27 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rspec.rb +35 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/stub_registry.rb +67 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/stub_request_snippet.rb +34 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/test_unit.rb +22 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/hash_counter.rb +32 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/hash_keys_stringifier.rb +25 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/hash_validator.rb +17 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/headers.rb +49 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/json.rb +78 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/query_mapper.rb +279 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/uri.rb +111 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/version_checker.rb +111 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/version.rb +3 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/webmock.rb +156 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock.rb +54 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/minitest/test_helper.rb +34 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/minitest/test_webmock.rb +9 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/minitest/webmock_spec.rb +60 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/curb/curb_spec.rb +466 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/curb/curb_spec_helper.rb +147 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/em_http_request/em_http_request_spec.rb +406 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +77 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/excon/excon_spec.rb +75 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/excon/excon_spec_helper.rb +50 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/http_rb/http_rb_spec.rb +73 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/http_rb/http_rb_spec_helper.rb +51 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/httpclient/httpclient_spec.rb +209 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/httpclient/httpclient_spec_helper.rb +57 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/manticore/manticore_spec.rb +56 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/net_http/net_http_shared.rb +142 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/net_http/net_http_spec.rb +317 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/net_http/net_http_spec_helper.rb +64 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/net_http/real_net_http_spec.rb +20 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/patron/patron_spec.rb +118 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/patron/patron_spec_helper.rb +54 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +313 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/callbacks.rb +147 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/complex_cross_concern_behaviors.rb +36 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/enabling_and_disabling_webmock.rb +95 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/precedence_of_stubs.rb +15 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/request_expectations.rb +916 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/returning_declared_responses.rb +388 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/stubbing_requests.rb +583 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +135 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +60 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/webmock_shared.rb +41 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/fixtures/test.txt +1 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/quality_spec.rb +84 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/spec_helper.rb +48 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/example_curl_output.txt +22 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/failures.rb +9 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/my_rack_app.rb +53 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/network_connection.rb +19 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/webmock_server.rb +69 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/api_spec.rb +75 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/errors_spec.rb +129 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/rack_response_spec.rb +112 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_body_diff_spec.rb +90 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_execution_verifier_spec.rb +208 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_pattern_spec.rb +590 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_registry_spec.rb +76 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_signature_snippet_spec.rb +89 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_signature_spec.rb +155 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_stub_spec.rb +199 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/response_spec.rb +282 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/stub_registry_spec.rb +103 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/stub_request_snippet_spec.rb +95 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/hash_counter_spec.rb +39 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/hash_keys_stringifier_spec.rb +27 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/headers_spec.rb +28 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/json_spec.rb +33 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/query_mapper_spec.rb +138 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/uri_spec.rb +299 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/version_checker_spec.rb +65 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/webmock_spec.rb +11 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/test/http_request.rb +24 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/test/shared_test.rb +95 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/test/test_helper.rb +23 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/test/test_webmock.rb +6 -0
- data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/webmock.gemspec +46 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/.gitignore +11 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/.rspec +3 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/.rubocop.yml +9 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/.travis.yml +9 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/Gemfile +5 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/LICENSE +202 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/README.md +79 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/Rakefile +28 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/VERSION +1 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/Vagrantfile +9 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/appveyor.yml +38 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/bin/rwinrmcp +86 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/changelog.md +60 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/core/file_transporter.rb +527 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/core/tmp_zip.rb +177 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/exceptions.rb +28 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/file_manager.rb +118 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/check_files.ps1.erb +49 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/checksum.ps1.erb +13 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/create_dir.ps1.erb +6 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/delete.ps1.erb +6 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/download.ps1.erb +8 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/exists.ps1.erb +10 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/extract_files.ps1.erb +52 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/scripts.rb +31 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs.rb +28 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/config-example.yml +3 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/integration/file_manager_spec.rb +224 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/integration/tmp_zip_spec.rb +26 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/matchers.rb +58 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/spec_helper.rb +71 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/unit/tmp_zip_spec.rb +79 -0
- data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/winrm-fs.gemspec +37 -0
- data/vendor/bundle/ruby/2.4.0/specifications/addressable-2.5.2.gemspec +39 -0
- data/vendor/bundle/ruby/2.4.0/specifications/hashdiff-0.3.7.gemspec +39 -0
- data/vendor/bundle/ruby/2.4.0/specifications/multi_json-1.12.2.gemspec +33 -0
- data/vendor/bundle/ruby/2.4.0/specifications/public_suffix-3.0.1.gemspec +41 -0
- data/vendor/bundle/ruby/2.4.0/specifications/webmock-2.3.2.gemspec +79 -0
- data/vendor/bundle/ruby/2.4.0/specifications/winrm-fs-1.1.1.gemspec +57 -0
- data/version.txt +1 -1
- metadata +295 -11
- data/plugins/guests/solaris11/cap/halt.rb +0 -26
- data/plugins/guests/solaris11/cap/insert_public_key.rb +0 -21
- data/plugins/guests/solaris11/cap/mount_virtualbox_shared_folder.rb +0 -45
- data/plugins/guests/solaris11/cap/remove_public_key.rb +0 -21
- data/plugins/guests/solaris11/cap/rsync.rb +0 -29
- data/test/unit/plugins/guests/solaris11/cap/halt_test.rb +0 -44
@@ -0,0 +1,79 @@
|
|
1
|
+
# File system operations over Windows Remote Management (WinRM) for Ruby
|
2
|
+
[![Build Status](https://travis-ci.org/WinRb/winrm-fs.svg?branch=master)](https://travis-ci.org/WinRb/winrm-fs)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/winrm-fs.svg)](http://badge.fury.io/rb/winrm-fs)
|
4
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/wm6apa8ojfhfmwsf?svg=true)](https://ci.appveyor.com/project/winrb/winrm-fs)
|
5
|
+
|
6
|
+
## Uploading files
|
7
|
+
Files may be copied from the local machine to the winrm endpoint. Individual files or directories, as well as arrays of files and directories may be specified:
|
8
|
+
```ruby
|
9
|
+
require 'winrm-fs'
|
10
|
+
|
11
|
+
connection = WinRM::Connection.new(...
|
12
|
+
file_manager = WinRM::FS::FileManager.new(connection)
|
13
|
+
|
14
|
+
# upload file.txt from the current working directory
|
15
|
+
file_manager.upload('file.txt', 'c:/file.txt')
|
16
|
+
|
17
|
+
# upload the my_dir directory to c:/foo/my_dir
|
18
|
+
file_manager.upload('/Users/sneal/my_dir', 'c:/foo/my_dir')
|
19
|
+
|
20
|
+
# upload multiple directories and a file to c:\programData
|
21
|
+
file_manager.upload([
|
22
|
+
'/Users/sneal/foo1',
|
23
|
+
'/Users/sneal/foo2'
|
24
|
+
'/Users/sneal/fluffy.txt'
|
25
|
+
], '$env:ProgramData')
|
26
|
+
```
|
27
|
+
|
28
|
+
### Optimizing WinRM settings
|
29
|
+
Since winrm-fs 1.0/winrm 2.0, files are uploaded using the PSRP protocol and transfer speeds are dramatically improved from previous versions. This is largely due to the fact that the size of chunks that can be transferred at one time are now governed by the `MaxEnvelopeSizekb` winrm configuration setting on the endpoint. This default to 500 on Windows 2012 R2 and 150 on Windows 2008 R2. You may experience much faster transfer rates on 2008 R2 by increasing this setting.
|
30
|
+
|
31
|
+
### Handling progress events
|
32
|
+
If you want to implement your own custom progress handling, you can pass a code
|
33
|
+
block and use the proggress data that `upload` yields to this block:
|
34
|
+
```ruby
|
35
|
+
file_manager.upload('c:/dev/my_dir', '$env:AppData') do |bytes_copied, total_bytes, local_path, remote_path|
|
36
|
+
puts "#{bytes_copied}bytes of #{total_bytes}bytes copied"
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## Troubleshooting
|
41
|
+
|
42
|
+
If you're having trouble, first of all its most likely a network or WinRM configuration
|
43
|
+
issue. Take a look at the [WinRM gem troubleshooting](https://github.com/WinRb/WinRM#troubleshooting)
|
44
|
+
first.
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
1. Fork it.
|
49
|
+
2. Create a branch (git checkout -b my_feature_branch)
|
50
|
+
3. Run the unit and integration tests (bundle exec rake integration)
|
51
|
+
4. Commit your changes (git commit -am "Added a sweet feature")
|
52
|
+
5. Push to the branch (git push origin my_feature_branch)
|
53
|
+
6. Create a pull requst from your branch into master (Please be sure to provide enough detail for us to cipher what this change is doing)
|
54
|
+
|
55
|
+
### Running the tests
|
56
|
+
|
57
|
+
We use Bundler to manage dependencies during development.
|
58
|
+
|
59
|
+
```
|
60
|
+
$ bundle install
|
61
|
+
```
|
62
|
+
|
63
|
+
Once you have the dependencies, you can run the unit tests with `rake`:
|
64
|
+
|
65
|
+
```
|
66
|
+
$ bundle exec rake spec
|
67
|
+
```
|
68
|
+
|
69
|
+
To run the integration tests you will need a Windows box with the WinRM service properly configured. Its easiest to use the Vagrant Windows box in the Vagrantilfe of this repo.
|
70
|
+
|
71
|
+
1. Create a Windows VM with WinRM configured (see above).
|
72
|
+
2. Copy the config-example.yml to config.yml - edit this file with your WinRM connection details.
|
73
|
+
3. Run `bundle exec rake integration`
|
74
|
+
|
75
|
+
## WinRM-fs Authors
|
76
|
+
* Shawn Neal (https://github.com/sneal)
|
77
|
+
* Matt Wrock (https://github.com/mwrock)
|
78
|
+
|
79
|
+
[Contributors](https://github.com/WinRb/winrm-fs/graphs/contributors)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
|
7
|
+
# Change to the directory of this file.
|
8
|
+
Dir.chdir(File.expand_path('../', __FILE__))
|
9
|
+
|
10
|
+
# For gem creation and bundling
|
11
|
+
require 'bundler/gem_tasks'
|
12
|
+
|
13
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
14
|
+
task.pattern = 'spec/unit/*_spec.rb'
|
15
|
+
task.rspec_opts = ['--color', '-f documentation']
|
16
|
+
end
|
17
|
+
|
18
|
+
# Run the integration test suite
|
19
|
+
RSpec::Core::RakeTask.new(:integration) do |task|
|
20
|
+
task.pattern = 'spec/integration/*_spec.rb'
|
21
|
+
task.rspec_opts = ['--color', '-f documentation']
|
22
|
+
end
|
23
|
+
|
24
|
+
RuboCop::RakeTask.new
|
25
|
+
|
26
|
+
task default: [:spec, :rubocop]
|
27
|
+
|
28
|
+
task all: [:default, :integration]
|
@@ -0,0 +1 @@
|
|
1
|
+
1.1.1
|
@@ -0,0 +1,38 @@
|
|
1
|
+
version: "master-{build}"
|
2
|
+
|
3
|
+
os: Windows Server 2012 R2
|
4
|
+
platform:
|
5
|
+
- x64
|
6
|
+
|
7
|
+
environment:
|
8
|
+
winrm_user: test_user
|
9
|
+
winrm_password: Pass@word1
|
10
|
+
|
11
|
+
matrix:
|
12
|
+
- ruby_version: "21"
|
13
|
+
winrm_endpoint: http://localhost:5985/wsman
|
14
|
+
|
15
|
+
clone_folder: c:\projects\winrm-fs
|
16
|
+
clone_depth: 1
|
17
|
+
branches:
|
18
|
+
only:
|
19
|
+
- master
|
20
|
+
|
21
|
+
install:
|
22
|
+
- ps: net user /add $env:winrm_user $env:winrm_password
|
23
|
+
- ps: net localgroup administrators $env:winrm_user /add
|
24
|
+
- ps: winrm set winrm/config/client/auth '@{Basic="true"}'
|
25
|
+
- ps: winrm set winrm/config/service/auth '@{Basic="true"}'
|
26
|
+
- ps: winrm set winrm/config/service '@{AllowUnencrypted="true"}'
|
27
|
+
- ps: $env:PATH="C:\Ruby$env:ruby_version\bin;$env:PATH"
|
28
|
+
- ps: Write-Host $env:PATH
|
29
|
+
- ps: ruby --version
|
30
|
+
- ps: gem --version
|
31
|
+
- ps: bundler --version
|
32
|
+
|
33
|
+
build_script:
|
34
|
+
- bundle install || bundle install || bundle install
|
35
|
+
|
36
|
+
test_script:
|
37
|
+
- SET SPEC_OPTS=--format progress
|
38
|
+
- bundle exec rake integration
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# Copyright 2014 Shawn Neal <sneal@sneal.net>
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
|
18
|
+
# TODO: refactor this
|
19
|
+
# rubocop:disable all
|
20
|
+
|
21
|
+
$LOAD_PATH.push File.expand_path('../../lib', __FILE__)
|
22
|
+
|
23
|
+
require 'io/console'
|
24
|
+
require 'winrm-fs'
|
25
|
+
|
26
|
+
def help_msg
|
27
|
+
puts 'Usage: rwinrmcp sourcefile user@host:directory/targetfile'
|
28
|
+
puts ''
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_options
|
32
|
+
options = {}
|
33
|
+
fail 'Missing required options' unless ARGV.length == 2
|
34
|
+
|
35
|
+
options[:source_path] = ARGV[0]
|
36
|
+
fail "Cannot find source file: #{options[:source_path]}" unless \
|
37
|
+
File.exist?(options[:source_path])
|
38
|
+
|
39
|
+
m = /^(?<user>[a-z0-9\.\!\$ _-]+)@{1}(?<host>[a-z0-9\.\-]+)(?<port>:[0-9]+)?:{1}(?<file>.+)/i.match(ARGV[1])
|
40
|
+
fail "#{ARGV[1]} is an invalid destination" unless m
|
41
|
+
options[:user] = m[:user]
|
42
|
+
options[:endpoint] = "http://#{m[:host]}#{m[:port] || ':5985'}/wsman"
|
43
|
+
options[:dest_path] = m[:file]
|
44
|
+
|
45
|
+
# Get the password
|
46
|
+
print 'Password: '
|
47
|
+
options[:pass] = STDIN.noecho(&:gets).chomp
|
48
|
+
puts
|
49
|
+
|
50
|
+
# Set some defaults required by WinRM WS
|
51
|
+
options[:auth_type] = :plaintext
|
52
|
+
options[:basic_auth_only] = true
|
53
|
+
|
54
|
+
options
|
55
|
+
rescue StandardError => e
|
56
|
+
puts e.message
|
57
|
+
help_msg
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
|
61
|
+
def file_manager(options)
|
62
|
+
service = WinRM::WinRMWebService.new(
|
63
|
+
options[:endpoint],
|
64
|
+
options[:auth_type].to_sym,
|
65
|
+
options)
|
66
|
+
WinRM::FS::FileManager.new(service)
|
67
|
+
end
|
68
|
+
|
69
|
+
def run(options)
|
70
|
+
bytes = file_manager(options).upload(options[:source_path], options[:dest_path])
|
71
|
+
puts "#{bytes} total bytes transfered"
|
72
|
+
exit 0
|
73
|
+
rescue Interrupt
|
74
|
+
puts 'exiting'
|
75
|
+
# ctrl-c
|
76
|
+
rescue WinRM::WinRMAuthorizationError
|
77
|
+
puts 'Authentication failed, bad user name or password'
|
78
|
+
exit 1
|
79
|
+
rescue StandardError => e
|
80
|
+
puts e.message
|
81
|
+
exit 1
|
82
|
+
end
|
83
|
+
|
84
|
+
run(parse_options)
|
85
|
+
|
86
|
+
# rubocop:enable all
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# WinRM-fs Gem Changelog
|
2
|
+
# 1.1.1
|
3
|
+
- Remove empty items from powershell pipeline when extracting zip files
|
4
|
+
|
5
|
+
# 1.1.0
|
6
|
+
- Convert MD5 hashes to SHA1.
|
7
|
+
|
8
|
+
# 1.0.2
|
9
|
+
- Fix `Pathname.glob` expansion of shortnames.
|
10
|
+
|
11
|
+
# 1.0.1
|
12
|
+
- Call ClearScriptBlockCache to prevent OutOfMemoryExceptions ClearScriptBlockCache
|
13
|
+
|
14
|
+
# 1.0.0
|
15
|
+
- Using winrm v2. File uploads just got a whole lot faster!
|
16
|
+
|
17
|
+
# 0.4.3
|
18
|
+
- Fix error handling with wmf5, filtering out progress output from inspected stderr.
|
19
|
+
|
20
|
+
# 0.4.2
|
21
|
+
- Improved Powershell error handling in metadata checking.
|
22
|
+
|
23
|
+
# 0.4.1
|
24
|
+
- Fixes a regression on Windows 2008 R2/Windows 7 and below where the WinRM service corrupts the check files metadata resulting in malformed destination paths.
|
25
|
+
|
26
|
+
# 0.4.0
|
27
|
+
- Correct the destination path of individual files. Always assume it is the full destination path unless it is an existing directory. This may potentialy break some callers expecting the remote path to be a directory that winrm-fs will create if missing as the destination of the local file. A new directory will not be created and the local file will be uploaded directly to the remote path.
|
28
|
+
|
29
|
+
# 0.3.2
|
30
|
+
- Fix re-extraction of cached directories from temp folder when there is more than one "clean" directory deleted from destination
|
31
|
+
|
32
|
+
# 0.3.1
|
33
|
+
- Widen logging version constraints to include 2.0 (matching WinRM core gem)
|
34
|
+
|
35
|
+
# 0.3.0
|
36
|
+
- Jetisons `CommandExecutor` now living in the core WinRM gem and swaps in implementation currently used in the winrm-transport gem. These changes should have little visible effect on current consumers of the `FileManager` class with these exceptions:
|
37
|
+
- BREAKING CHANGE: When uploading a directory and the destination directory exists on the endpoint, the source base directory will be created below the destination directory on the endpoint and the source directory contents will be unzipped to that location. Prior to this release, the contents of the source directory would be unzipped to an existing destination directory without creating the source base directory. This new behavior is more consistent with SCP and other well known shell copy commands.
|
38
|
+
- `Upload` may now receive an array of source files and directories rather than just a single file or directory path.
|
39
|
+
|
40
|
+
# 0.2.4
|
41
|
+
- Fix issue 21, downloading files is extremely slow.
|
42
|
+
- Add zip file creation debug logging.
|
43
|
+
|
44
|
+
# 0.2.3
|
45
|
+
- Fix yielding progress data, issue #23
|
46
|
+
|
47
|
+
# 0.2.2
|
48
|
+
- Fix powershell streams leaking to standard error breaking Windows 10, issue #18
|
49
|
+
|
50
|
+
# 0.2.1
|
51
|
+
- Fixed issue 16 creating zip file on Windows
|
52
|
+
|
53
|
+
# 0.2.0
|
54
|
+
- Redesigned temp zip file creation system
|
55
|
+
- Fixed lots of small edge case issues especially with directory uploads
|
56
|
+
- Simplified file manager upload method API to take only a single source file or directory
|
57
|
+
- Expanded acceptable username and hostnames for rwinrmcp
|
58
|
+
|
59
|
+
# 0.1.0
|
60
|
+
- Initial alpha quality release
|
@@ -0,0 +1,527 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: Fletcher (<fnichol@nichol.ca>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015, Fletcher Nichol
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require 'benchmark'
|
20
|
+
require 'csv'
|
21
|
+
require 'digest'
|
22
|
+
require 'securerandom'
|
23
|
+
require 'stringio'
|
24
|
+
|
25
|
+
require 'winrm-fs/core/tmp_zip'
|
26
|
+
|
27
|
+
module WinRM
|
28
|
+
module FS
|
29
|
+
module Core
|
30
|
+
# Wrapped exception for any internally raised WinRM-related errors.
|
31
|
+
#
|
32
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
33
|
+
class FileTransporterFailed < ::WinRM::WinRMError; end
|
34
|
+
# rubocop:disable MethodLength, AbcSize, ClassLength
|
35
|
+
|
36
|
+
# Object which can upload one or more files or directories to a remote
|
37
|
+
# host over WinRM using PowerShell scripts and CMD commands. Note that
|
38
|
+
# this form of file transfer is *not* ideal and extremely costly on both
|
39
|
+
# the local and remote sides. Great pains are made to minimize round
|
40
|
+
# trips to the remote host and to minimize the number of PowerShell
|
41
|
+
# sessions being invoked which can be 2 orders of magnitude more
|
42
|
+
# expensive than vanilla CMD commands.
|
43
|
+
#
|
44
|
+
# This object is supported by a `PowerShell` instance as it
|
45
|
+
# depends on the `#run` API contract.
|
46
|
+
#
|
47
|
+
# An optional logger can be supplied, assuming it can respond to the
|
48
|
+
# `#debug` and `#debug?` messages.
|
49
|
+
#
|
50
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
51
|
+
# @author Matt Wrock <matt@mattwrock.com>
|
52
|
+
class FileTransporter
|
53
|
+
# Creates a FileTransporter given a PowerShell object.
|
54
|
+
#
|
55
|
+
# @param shell [PowerShell] a winrm PowerShell object
|
56
|
+
def initialize(shell, opts = {})
|
57
|
+
@shell = shell
|
58
|
+
@logger = shell.logger
|
59
|
+
@id_generator = opts.fetch(:id_generator) { -> { SecureRandom.uuid } }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Uploads a collection of files and/or directories to the remote host.
|
63
|
+
#
|
64
|
+
# **TODO Notes:**
|
65
|
+
# * options could specify zip mode, zip options, etc.
|
66
|
+
# * maybe option to set tmpfile base dir to override $env:PATH?
|
67
|
+
# * progress yields block like net-scp progress
|
68
|
+
# * final API: def upload(locals, remote, _options = {}, &_progress)
|
69
|
+
#
|
70
|
+
# @param locals [Array<String>,String] one or more local file or
|
71
|
+
# directory paths
|
72
|
+
# @param remote [String] the base destination path on the remote host
|
73
|
+
# @return [Hash] report hash, keyed by the local SHA1 digest
|
74
|
+
def upload(locals, remote)
|
75
|
+
files = nil
|
76
|
+
report = nil
|
77
|
+
remote = remote.to_s
|
78
|
+
|
79
|
+
elapsed1 = Benchmark.measure do
|
80
|
+
files = make_files_hash(Array(locals), remote)
|
81
|
+
report = check_files(files)
|
82
|
+
merge_with_report!(files, report)
|
83
|
+
reconcile_destinations!(files)
|
84
|
+
end
|
85
|
+
total_size = total_base64_transfer_size(files)
|
86
|
+
|
87
|
+
elapsed2 = Benchmark.measure do
|
88
|
+
report = stream_upload_files(files) do |local_path, xfered|
|
89
|
+
yield xfered, total_size, local_path, remote if block_given?
|
90
|
+
end
|
91
|
+
merge_with_report!(files, report)
|
92
|
+
end
|
93
|
+
|
94
|
+
elapsed3 = Benchmark.measure do
|
95
|
+
report = extract_files(files)
|
96
|
+
merge_with_report!(files, report)
|
97
|
+
cleanup(files)
|
98
|
+
end
|
99
|
+
|
100
|
+
logger.debug(
|
101
|
+
"Uploaded #{files.keys.size} items " \
|
102
|
+
"dirty_check: #{duration(elapsed1.real)} " \
|
103
|
+
"stream_files: #{duration(elapsed2.real)} " \
|
104
|
+
"extract: #{duration(elapsed3.real)} " \
|
105
|
+
)
|
106
|
+
|
107
|
+
[total_size, files]
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
# @return [String] the Array pack template for Base64 encoding a stream
|
113
|
+
# of data
|
114
|
+
# @api private
|
115
|
+
BASE64_PACK = 'm0'.freeze
|
116
|
+
|
117
|
+
# @return [String] the directory where temporary upload artifacts are
|
118
|
+
# persisted
|
119
|
+
# @api private
|
120
|
+
TEMP_UPLOAD_DIRECTORY = '$env:TEMP\\winrm-upload'.freeze
|
121
|
+
|
122
|
+
# @return [#debug,#debug?] the logger
|
123
|
+
# @api private
|
124
|
+
attr_reader :logger
|
125
|
+
|
126
|
+
# @return [Winrm::Shells::Powershell] a WinRM Powershell shell
|
127
|
+
# @api private
|
128
|
+
attr_reader :shell
|
129
|
+
|
130
|
+
# @return [Integer] the maximum number of bytes to send per request
|
131
|
+
# when streaming a file. This is optimized to send as much data
|
132
|
+
# as allowed in a single PSRP fragment
|
133
|
+
# @api private
|
134
|
+
def max_encoded_write
|
135
|
+
@max_encoded_write ||= begin
|
136
|
+
empty_command = WinRM::PSRP::MessageFactory.create_pipeline_message(
|
137
|
+
'00000000-0000-0000-0000-000000000000',
|
138
|
+
'00000000-0000-0000-0000-000000000000',
|
139
|
+
stream_command('')
|
140
|
+
)
|
141
|
+
shell.max_fragment_blob_size - empty_command.bytes.length
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Examines the files and corrects the file destination if it is
|
146
|
+
# targeting an existing folder. In this case, the destination path
|
147
|
+
# will have the base name of the source file appended. This only
|
148
|
+
# applies to file uploads and not to folder uploads.
|
149
|
+
#
|
150
|
+
# @param files [Hash] files hash, keyed by the local SHA1 digest
|
151
|
+
# @return [Hash] a report hash, keyed by the local SHA1 digest
|
152
|
+
# @api private
|
153
|
+
def reconcile_destinations!(files)
|
154
|
+
files.each do |_, data|
|
155
|
+
if data['target_is_folder'] == 'True'
|
156
|
+
data['dst'] = File.join(data['dst'], File.basename(data['src']))
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Adds an entry to a files Hash (keyed by local SHA1 digest) for a
|
162
|
+
# directory. When a directory is added, a temporary Zip file is created
|
163
|
+
# containing the contents of the directory and any file-related data
|
164
|
+
# such as SHA1 digest, size, etc. will be referring to the Zip file.
|
165
|
+
#
|
166
|
+
# @param hash [Hash] hash to be mutated
|
167
|
+
# @param dir [String] directory path to be Zipped and added
|
168
|
+
# @param remote [String] path to destination on remote host
|
169
|
+
# @api private
|
170
|
+
def add_directory_hash!(hash, dir, remote)
|
171
|
+
logger.debug "creating hash for directory #{remote}"
|
172
|
+
zip_io = TmpZip.new(dir, logger)
|
173
|
+
zip_sha1 = sha1sum(zip_io.path)
|
174
|
+
|
175
|
+
hash[zip_sha1] = {
|
176
|
+
'src' => dir,
|
177
|
+
'src_zip' => zip_io.path.to_s,
|
178
|
+
'zip_io' => zip_io,
|
179
|
+
'tmpzip' => "#{TEMP_UPLOAD_DIRECTORY}\\tmpzip-#{zip_sha1}.zip",
|
180
|
+
'dst' => "#{remote}\\#{File.basename(dir)}",
|
181
|
+
'size' => File.size(zip_io.path)
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
# Adds an entry to a files Hash (keyed by local SHA1 digest) for a file.
|
186
|
+
#
|
187
|
+
# @param hash [Hash] hash to be mutated
|
188
|
+
# @param local [String] file path
|
189
|
+
# @param remote [String] path to destination on remote host
|
190
|
+
# @api private
|
191
|
+
def add_file_hash!(hash, local, remote)
|
192
|
+
logger.debug "creating hash for file #{remote}"
|
193
|
+
|
194
|
+
hash[sha1sum(local)] = {
|
195
|
+
'src' => local,
|
196
|
+
'dst' => remote,
|
197
|
+
'size' => File.size(local)
|
198
|
+
}
|
199
|
+
end
|
200
|
+
|
201
|
+
# Runs the check_files PowerShell script against a collection of
|
202
|
+
# destination path/SHA1 checksum pairs. The PowerShell script returns
|
203
|
+
# its results as a CSV-formatted report which is converted into a Ruby
|
204
|
+
# Hash.
|
205
|
+
#
|
206
|
+
# @param files [Hash] files hash, keyed by the local SHA1 digest
|
207
|
+
# @return [Hash] a report hash, keyed by the local SHA1 digest
|
208
|
+
# @api private
|
209
|
+
def check_files(files)
|
210
|
+
logger.debug 'Running check_files.ps1'
|
211
|
+
hash_file = check_files_ps_hash(files)
|
212
|
+
script = WinRM::FS::Scripts.render('check_files', hash_file: hash_file)
|
213
|
+
parse_response(shell.run(script))
|
214
|
+
end
|
215
|
+
|
216
|
+
# Constructs a collection of destination path/SHA1 checksum pairs as a
|
217
|
+
# String representation of the contents of a PowerShell Hash Table.
|
218
|
+
#
|
219
|
+
# @param files [Hash] files hash, keyed by the local SHA1 digest
|
220
|
+
# @return [String] the inner contents of a PowerShell Hash Table
|
221
|
+
# @api private
|
222
|
+
def check_files_ps_hash(files)
|
223
|
+
hash = files.map do |sha1, data|
|
224
|
+
[
|
225
|
+
sha1,
|
226
|
+
{
|
227
|
+
'target' => data.fetch('tmpzip', data['dst']),
|
228
|
+
'src_basename' => File.basename(data['src']),
|
229
|
+
'dst' => data['dst']
|
230
|
+
}
|
231
|
+
]
|
232
|
+
end
|
233
|
+
ps_hash(Hash[hash])
|
234
|
+
end
|
235
|
+
|
236
|
+
# Performs any final cleanup on the report Hash and removes any
|
237
|
+
# temporary files/resources used in the upload task.
|
238
|
+
#
|
239
|
+
# @param files [Hash] a files hash
|
240
|
+
# @api private
|
241
|
+
def cleanup(files)
|
242
|
+
files.select { |_, data| data.key?('zip_io') }.each do |sha1, data|
|
243
|
+
data.fetch('zip_io').unlink
|
244
|
+
files.fetch(sha1).delete('zip_io')
|
245
|
+
logger.debug "Cleaned up src_zip #{data['src_zip']}"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Runs the extract_files PowerShell script against a collection of
|
250
|
+
# temporary file/destination path pairs. The PowerShell script returns
|
251
|
+
# its results as a CSV-formatted report which is converted into a Ruby
|
252
|
+
# Hash. The script will not be invoked if there are no zip files
|
253
|
+
# present in the incoming files Hash.
|
254
|
+
#
|
255
|
+
# @param files [Hash] files hash, keyed by the local SHA1 digest
|
256
|
+
# @return [Hash] a report hash, keyed by the local SHA1 digest
|
257
|
+
# @api private
|
258
|
+
def extract_files(files)
|
259
|
+
extracted_files = extract_files_ps_hash(files)
|
260
|
+
|
261
|
+
if extracted_files == ps_hash({})
|
262
|
+
logger.debug 'No remote files to extract, skipping'
|
263
|
+
{}
|
264
|
+
else
|
265
|
+
logger.debug 'Running extract_files.ps1'
|
266
|
+
script = WinRM::FS::Scripts.render('extract_files', hash_file: extracted_files)
|
267
|
+
|
268
|
+
parse_response(shell.run(script))
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
# Constructs a collection of temporary file/destination path pairs for
|
273
|
+
# all zipped folders as a String representation of the contents of a
|
274
|
+
# PowerShell Hash Table.
|
275
|
+
#
|
276
|
+
# @param files [Hash] files hash, keyed by the local SHA1 digest
|
277
|
+
# @return [String] the inner contents of a PowerShell Hash Table
|
278
|
+
# @api private
|
279
|
+
def extract_files_ps_hash(files)
|
280
|
+
file_data = files.select { |_, data| data.key?('tmpzip') }
|
281
|
+
|
282
|
+
result = file_data.map do |sha1, data|
|
283
|
+
val = { 'dst' => data['dst'] }
|
284
|
+
val['tmpzip'] = data['tmpzip'] if data['tmpzip']
|
285
|
+
|
286
|
+
[sha1, val]
|
287
|
+
end
|
288
|
+
|
289
|
+
ps_hash(Hash[result])
|
290
|
+
end
|
291
|
+
|
292
|
+
# Returns a formatted string representing a duration in seconds.
|
293
|
+
#
|
294
|
+
# @param total [Integer] the total number of seconds
|
295
|
+
# @return [String] a formatted string of the form (XmYY.00s)
|
296
|
+
def duration(total)
|
297
|
+
total = 0 if total.nil?
|
298
|
+
minutes = (total / 60).to_i
|
299
|
+
seconds = (total - (minutes * 60))
|
300
|
+
format('(%dm%.2fs)', minutes, seconds)
|
301
|
+
end
|
302
|
+
|
303
|
+
# Contructs a Hash of files or directories, keyed by the local SHA1
|
304
|
+
# digest. Each file entry has a source and destination set, at a
|
305
|
+
# minimum.
|
306
|
+
#
|
307
|
+
# @param locals [Array<String>] a collection of local files or
|
308
|
+
# directories
|
309
|
+
# @param remote [String] the base destination path on the remote host
|
310
|
+
# @return [Hash] files hash, keyed by the local SHA1 digest
|
311
|
+
# @api private
|
312
|
+
def make_files_hash(locals, remote)
|
313
|
+
hash = {}
|
314
|
+
locals.each do |local|
|
315
|
+
local = local.to_s
|
316
|
+
expanded = File.expand_path(local)
|
317
|
+
expanded += local[-1] if local.end_with?('/', '\\')
|
318
|
+
|
319
|
+
if File.file?(expanded)
|
320
|
+
add_file_hash!(hash, expanded, remote)
|
321
|
+
elsif File.directory?(expanded)
|
322
|
+
add_directory_hash!(hash, expanded, remote)
|
323
|
+
else
|
324
|
+
fail Errno::ENOENT, "No such file or directory #{expanded}"
|
325
|
+
end
|
326
|
+
end
|
327
|
+
hash
|
328
|
+
end
|
329
|
+
|
330
|
+
# @return [String] the SHA1 digest of a local file
|
331
|
+
# @api private
|
332
|
+
def sha1sum(local)
|
333
|
+
Digest::SHA1.file(local).hexdigest
|
334
|
+
end
|
335
|
+
|
336
|
+
# Destructively merges a report Hash into an existing files Hash.
|
337
|
+
# **Note:** this method mutates the files Hash.
|
338
|
+
#
|
339
|
+
# @param files [Hash] files hash, keyed by the local SHA1 digest
|
340
|
+
# @param report [Hash] report hash, keyed by the local SHA1 digest
|
341
|
+
# @api private
|
342
|
+
def merge_with_report!(files, report)
|
343
|
+
files.merge!(report) { |_, oldval, newval| oldval.merge(newval) }
|
344
|
+
end
|
345
|
+
|
346
|
+
# @param depth [Integer] number of padding characters (default: `0`)
|
347
|
+
# @return [String] a whitespace padded string of the given length
|
348
|
+
# @api private
|
349
|
+
def pad(depth = 0)
|
350
|
+
' ' * depth
|
351
|
+
end
|
352
|
+
|
353
|
+
# Parses response of a PowerShell script or CMD command which contains
|
354
|
+
# a CSV-formatted document in the standard output stream.
|
355
|
+
#
|
356
|
+
# @param output [WinRM::Output] output object with stdout, stderr, and
|
357
|
+
# exit code
|
358
|
+
# @return [Hash] report hash, keyed by the local SHA1 digest
|
359
|
+
# @api private
|
360
|
+
def parse_response(output)
|
361
|
+
exitcode = output.exitcode
|
362
|
+
stderr = output.stderr
|
363
|
+
|
364
|
+
if exitcode != 0
|
365
|
+
fail FileTransporterFailed, "[#{self.class}] Upload failed " \
|
366
|
+
"(exitcode: #{exitcode})\n#{stderr}"
|
367
|
+
elsif stderr != '\r\n' && stderr != ''
|
368
|
+
fail FileTransporterFailed, "[#{self.class}] Upload failed " \
|
369
|
+
"(exitcode: 0), but stderr present\n#{stderr}"
|
370
|
+
end
|
371
|
+
|
372
|
+
logger.debug 'Parsing CSV Response'
|
373
|
+
logger.debug output.stdout
|
374
|
+
|
375
|
+
array = CSV.parse(output.stdout, headers: true).map(&:to_hash)
|
376
|
+
array.each { |h| h.each { |key, value| h[key] = nil if value == '' } }
|
377
|
+
Hash[array.map { |entry| [entry.fetch('src_sha1'), entry] }]
|
378
|
+
end
|
379
|
+
|
380
|
+
# Converts a Ruby hash into a PowerShell hash table, represented in a
|
381
|
+
# String.
|
382
|
+
#
|
383
|
+
# @param obj [Object] source Hash or object when used in recursive
|
384
|
+
# calls
|
385
|
+
# @param depth [Integer] padding depth, used in recursive calls
|
386
|
+
# (default: `0`)
|
387
|
+
# @return [String] a PowerShell hash table
|
388
|
+
# @api private
|
389
|
+
def ps_hash(obj, depth = 0)
|
390
|
+
if obj.is_a?(Hash)
|
391
|
+
obj.map do |k, v|
|
392
|
+
%(#{pad(depth + 2)}#{ps_hash(k)} = #{ps_hash(v, depth + 2)})
|
393
|
+
end.join(";\n").insert(0, "@{\n").insert(-1, "\n#{pad(depth)}}")
|
394
|
+
else
|
395
|
+
%("#{obj}")
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
# Uploads an IO stream to a Base64-encoded destination file.
|
400
|
+
#
|
401
|
+
# **Implementation Note:** Some of the code in this method may appear
|
402
|
+
# slightly too dense and while adding additional variables would help,
|
403
|
+
# the code is written very precisely to avoid unwanted allocations
|
404
|
+
# which will bloat the Ruby VM's object space (and memory footprint).
|
405
|
+
# The goal here is to stream potentially large files to a remote host
|
406
|
+
# while not loading the entire file into memory first, then Base64
|
407
|
+
# encoding it--duplicating the file in memory again.
|
408
|
+
#
|
409
|
+
# @param input_io [#read] a readable stream or object to be uploaded
|
410
|
+
# @param dest [String] path to the destination file on the remote host
|
411
|
+
# @return [Integer,Integer] the number of resulting upload chunks and
|
412
|
+
# the number of bytes transferred to the remote host
|
413
|
+
# @api private
|
414
|
+
def stream_upload(input_io, dest)
|
415
|
+
read_size = ((max_encoded_write - dest.length) / 4) * 3
|
416
|
+
chunk, bytes = 1, 0
|
417
|
+
buffer = ''
|
418
|
+
shell.run(<<-EOS
|
419
|
+
$to = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath("#{dest}")
|
420
|
+
$parent = Split-Path $to
|
421
|
+
if(!(Test-path $parent)) { mkdir $parent | Out-Null }
|
422
|
+
$fileStream = New-Object -TypeName System.IO.FileStream -ArgumentList @(
|
423
|
+
$to,
|
424
|
+
[system.io.filemode]::Create,
|
425
|
+
[System.io.FileAccess]::Write,
|
426
|
+
[System.IO.FileShare]::ReadWrite
|
427
|
+
)
|
428
|
+
|
429
|
+
# Powershell caches ScrpitBlocks in a dictionary
|
430
|
+
# keyed on the script block text. Thats just great
|
431
|
+
# unless the script is super large and called a gillion
|
432
|
+
# times like we might do. In such a case it will saturate the
|
433
|
+
# Large Object Heap and lead to Out Of Memory exceptions
|
434
|
+
# for large files or folders. So we call the internal method
|
435
|
+
# ClearScriptBlockCache to clear it.
|
436
|
+
$bindingFlags= [Reflection.BindingFlags] "NonPublic,Static"
|
437
|
+
$method = [scriptblock].GetMethod("ClearScriptBlockCache", $bindingFlags)
|
438
|
+
EOS
|
439
|
+
)
|
440
|
+
|
441
|
+
while input_io.read(read_size, buffer)
|
442
|
+
bytes += (buffer.bytesize / 3 * 4)
|
443
|
+
shell.run(stream_command([buffer].pack(BASE64_PACK)))
|
444
|
+
logger.debug "Wrote chunk #{chunk} for #{dest}" if chunk % 25 == 0
|
445
|
+
chunk += 1
|
446
|
+
yield bytes if block_given?
|
447
|
+
end
|
448
|
+
shell.run('$fileStream.Dispose()')
|
449
|
+
buffer = nil # rubocop:disable Lint/UselessAssignment
|
450
|
+
|
451
|
+
[chunk - 1, bytes]
|
452
|
+
end
|
453
|
+
|
454
|
+
def stream_command(encoded_bytes)
|
455
|
+
<<-EOS
|
456
|
+
if($method) { $method.Invoke($Null, $Null) }
|
457
|
+
$bytes=[Convert]::FromBase64String('#{encoded_bytes}')
|
458
|
+
$fileStream.Write($bytes, 0, $bytes.length)
|
459
|
+
EOS
|
460
|
+
end
|
461
|
+
|
462
|
+
# Uploads a local file.
|
463
|
+
#
|
464
|
+
# @param src [String] path to a local file
|
465
|
+
# @param dest [String] path to the file on the remote host
|
466
|
+
# @return [Integer,Integer] the number of resulting upload chunks and
|
467
|
+
# the number of bytes transferred to the remote host
|
468
|
+
# @api private
|
469
|
+
def stream_upload_file(src, dest, &block)
|
470
|
+
logger.debug "Uploading #{src} to #{dest}"
|
471
|
+
chunks, bytes = 0, 0
|
472
|
+
elapsed = Benchmark.measure do
|
473
|
+
File.open(src, 'rb') do |io|
|
474
|
+
chunks, bytes = stream_upload(io, dest, &block)
|
475
|
+
end
|
476
|
+
end
|
477
|
+
logger.debug(
|
478
|
+
"Finished uploading #{src} to #{dest} " \
|
479
|
+
"(#{bytes.to_f / 1000} KB over #{chunks} chunks) " \
|
480
|
+
"in #{duration(elapsed.real)}"
|
481
|
+
)
|
482
|
+
|
483
|
+
[chunks, bytes]
|
484
|
+
end
|
485
|
+
|
486
|
+
# Uploads a collection of "dirty" files to the remote host as
|
487
|
+
# Base64-encoded temporary files. A "dirty" file is one which has the
|
488
|
+
# `"chk_dirty"` option set to `"True"` in the incoming files Hash.
|
489
|
+
#
|
490
|
+
# @param files [Hash] files hash, keyed by the local SHA1 digest
|
491
|
+
# @return [Hash] a report hash, keyed by the local SHA1 digest
|
492
|
+
# @api private
|
493
|
+
def stream_upload_files(files)
|
494
|
+
response = {}
|
495
|
+
files.each do |sha1, data|
|
496
|
+
src = data.fetch('src_zip', data['src'])
|
497
|
+
if data['chk_dirty'] == 'True'
|
498
|
+
response[sha1] = { 'dest' => data['tmpzip'] || data['dst'] }
|
499
|
+
chunks, bytes = stream_upload_file(src, data['tmpzip'] || data['dst']) do |xfered|
|
500
|
+
yield data['src'], xfered
|
501
|
+
end
|
502
|
+
response[sha1]['chunks'] = chunks
|
503
|
+
response[sha1]['xfered'] = bytes
|
504
|
+
else
|
505
|
+
logger.debug "File #{data['dst']} is up to date, skipping"
|
506
|
+
end
|
507
|
+
end
|
508
|
+
response
|
509
|
+
end
|
510
|
+
|
511
|
+
# Total by byte count to be transferred.
|
512
|
+
# Calculates count based on the sum of base64 encoded content size
|
513
|
+
# of all files base 64 that are dirty.
|
514
|
+
#
|
515
|
+
# @param files [Hash] files hash, keyed by the local SHA1 digest
|
516
|
+
# @return [Fixnum] total byte size
|
517
|
+
# @api private
|
518
|
+
def total_base64_transfer_size(files)
|
519
|
+
size = 0
|
520
|
+
files.values.each { |file| size += file['size'] if file['chk_dirty'] == 'True' }
|
521
|
+
size / 3 * 4
|
522
|
+
end
|
523
|
+
end
|
524
|
+
# rubocop:enable MethodLength, AbcSize, ClassLength
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|