sshkit-backends-netssh_global 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Brewfile +5 -0
- data/Gemfile +3 -0
- data/LICENSE.md +674 -0
- data/README.md +59 -0
- data/Rakefile +27 -0
- data/Vagrantfile +20 -0
- data/lib/sshkit/backends/netssh_global.rb +87 -0
- data/lib/sshkit/backends/version.rb +7 -0
- data/lib/sshkit/command_sudo_ssh_forward.rb +74 -0
- data/sshkit-backends-netssh_global.gemspec +28 -0
- data/test/boxes.json +13 -0
- data/test/functional/backends/test_netssh_global.rb +300 -0
- data/test/helper.rb +33 -0
- data/test/support/vagrant_wrapper.rb +63 -0
- data/test/unit/backends/test_netssh_global.rb +59 -0
- data/test/unit/test_command_sudo_ssh_forward.rb +239 -0
- metadata +147 -0
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# SSHKit Backends Netssh Global
|
2
|
+
|
3
|
+
**SSHKit Backends Netssh Global** is a backend to be used in conjunction with
|
4
|
+
Capistrano 3 and SSHKit to allow global configuration to be set. For example,
|
5
|
+
all commands can be run under a different user or folder - without modifying the
|
6
|
+
command.
|
7
|
+
|
8
|
+
This is designed to make it possible for Capistrano 3 to deploy on systems where
|
9
|
+
users login as one identity and then need to sudo to a different identity for
|
10
|
+
each command.
|
11
|
+
|
12
|
+
This works globally so that default tasks will automatically `sudo` and `cd`
|
13
|
+
without modification. This allows the default tasks to be used in this kind of
|
14
|
+
setup without them being altered.
|
15
|
+
|
16
|
+
If a task specifically `sudo`'s or `cd`'s then the global setting will not take
|
17
|
+
effect.
|
18
|
+
|
19
|
+
In some setups the ssh agent also needs to be forwarded (such as git clone).
|
20
|
+
Here the setting `ssh_commands` can be set to automatically forward the ssh
|
21
|
+
agent to the sudo user for certain commands.
|
22
|
+
|
23
|
+
### To run tests
|
24
|
+
|
25
|
+
To setup an OSX machine to run the tests, install Homebrew then:
|
26
|
+
|
27
|
+
```
|
28
|
+
brew tap Homebrew/bundle
|
29
|
+
brew bundle
|
30
|
+
vagrant up --provision
|
31
|
+
bundle
|
32
|
+
rake
|
33
|
+
```
|
34
|
+
|
35
|
+
### Usage
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require 'sshkit/backends/netssh_global'
|
39
|
+
|
40
|
+
SSHKit::Backend::NetsshGlobal.configure do |config|
|
41
|
+
config.owner = 'bob' # Which user to sudo as for every command
|
42
|
+
config.directory = '/home/bob' # Can be specified if it is important to default commands to run in a
|
43
|
+
# certain directory. This can be used to overcome permission problems when
|
44
|
+
# sudo'ing
|
45
|
+
config.ssh_commands = [:git] # Setting for which commands require SSH forwarding
|
46
|
+
config.shell = 'bash -l' # Setting that allows the shell that sudo runs to be overriden
|
47
|
+
end
|
48
|
+
|
49
|
+
# Per host configuration
|
50
|
+
Host.new("example.com").tap do |h|
|
51
|
+
h.properties.owner = 'fred'
|
52
|
+
h.properties.directory = '/home/fred'
|
53
|
+
h.properties.ssh_commands = [:git, :bundle]
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
### Credits
|
58
|
+
|
59
|
+
The code and test suite are built on top of [SSHKit](http://github.com/capistrano/sshkit).
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc "Run all tests"
|
9
|
+
task :test => ['test:units', 'test:functional']
|
10
|
+
|
11
|
+
namespace :test do
|
12
|
+
|
13
|
+
Rake::TestTask.new(:units) do |t|
|
14
|
+
t.libs << "test"
|
15
|
+
t.test_files = FileList['test/unit/**/test*.rb']
|
16
|
+
end
|
17
|
+
|
18
|
+
Rake::TestTask.new(:functional) do |t|
|
19
|
+
t.libs << "test"
|
20
|
+
t.test_files = FileList['test/functional/**/test*.rb']
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
Rake::Task["test:functional"].enhance do
|
26
|
+
warn "Remember there are still some VMs running, kill them with `vagrant halt` if you are finished using them."
|
27
|
+
end
|
data/Vagrantfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
VAGRANTFILE_API_VERSION = "2"
|
2
|
+
|
3
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
4
|
+
config.vm.box = 'hashicorp/precise64'
|
5
|
+
|
6
|
+
json_config_path = File.join("test", "boxes.json")
|
7
|
+
list = File.open(json_config_path).read
|
8
|
+
list = JSON.parse(list)
|
9
|
+
|
10
|
+
list.each do |vm|
|
11
|
+
config.vm.define vm["name"] do |web|
|
12
|
+
web.vm.network "forwarded_port", guest: 22, host: vm["port"]
|
13
|
+
web.vm.provision "shell", inline: "apt-get update && apt-get install --yes acl csh"
|
14
|
+
|
15
|
+
vm["users"].each do |user|
|
16
|
+
web.vm.provision "shell", inline: "useradd --create-home #{user}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'sshkit/command_sudo_ssh_forward'
|
2
|
+
|
3
|
+
module SSHKit
|
4
|
+
module Backend
|
5
|
+
class NetsshGlobal < Netssh
|
6
|
+
class Configuration < Netssh::Configuration
|
7
|
+
attr_accessor :owner, :directory, :shell
|
8
|
+
attr_writer :ssh_commands
|
9
|
+
|
10
|
+
def ssh_commands
|
11
|
+
@ssh_commands || [:ssh, :git, :'ssh-add', :bundle]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def config
|
17
|
+
@config ||= Configuration.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@pool = SSHKit::Backend::ConnectionPool.new
|
22
|
+
|
23
|
+
def upload!(local, remote, options = {})
|
24
|
+
execute :setfacl, "-m u:#{ssh_user}:rwx #{File.dirname(remote)}; true"
|
25
|
+
execute :setfacl, "-m u:#{ssh_user}:rw #{remote}; true"
|
26
|
+
super
|
27
|
+
as :root do
|
28
|
+
# Required as uploaded file is owned by SSH user, not owner
|
29
|
+
execute :chown, property(:owner), remote
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def user
|
36
|
+
@user || property(:owner)
|
37
|
+
end
|
38
|
+
|
39
|
+
def ssh_user
|
40
|
+
host.user || configure_host.ssh_options.fetch(:user)
|
41
|
+
end
|
42
|
+
|
43
|
+
def pwd
|
44
|
+
@pwd.nil? ? property(:directory) : File.join(@pwd)
|
45
|
+
end
|
46
|
+
|
47
|
+
def property(name)
|
48
|
+
host.properties.public_send(name) || self.class.config.public_send(name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def with_ssh
|
52
|
+
configure_host
|
53
|
+
conn = self.class.pool.checkout(
|
54
|
+
String(host.hostname),
|
55
|
+
host.username,
|
56
|
+
host.netssh_options,
|
57
|
+
&Net::SSH.method(:start)
|
58
|
+
)
|
59
|
+
begin
|
60
|
+
yield conn.connection
|
61
|
+
ensure
|
62
|
+
self.class.pool.checkin conn
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def configure_host
|
67
|
+
host.tap do |h|
|
68
|
+
h.ssh_options = self.class.config.ssh_options.merge(host.ssh_options || {})
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def command(*args)
|
73
|
+
options = args.extract_options!
|
74
|
+
options.merge!(
|
75
|
+
in: pwd,
|
76
|
+
env: @env,
|
77
|
+
host: configure_host,
|
78
|
+
user: user,
|
79
|
+
group: @group,
|
80
|
+
ssh_commands: property(:ssh_commands),
|
81
|
+
shell: property(:shell)
|
82
|
+
)
|
83
|
+
SSHKit::CommandSudoSshForward.new(*[*args, options])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module SSHKit
|
2
|
+
class CommandSudoSshForward < SSHKit::Command
|
3
|
+
def to_command
|
4
|
+
return command.to_s unless should_map?
|
5
|
+
|
6
|
+
within do
|
7
|
+
ssh_agent do
|
8
|
+
umask do
|
9
|
+
with do
|
10
|
+
user do
|
11
|
+
in_background do
|
12
|
+
group do
|
13
|
+
to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def environment_hash
|
24
|
+
default_env.merge(options_env)
|
25
|
+
end
|
26
|
+
|
27
|
+
def ssh_agent(&block)
|
28
|
+
return yield unless ssh_forwarding_required?
|
29
|
+
"setfacl -m #{options[:user]}:x $(dirname $SSH_AUTH_SOCK) && setfacl -m #{options[:user]}:rw $SSH_AUTH_SOCK && %s" % yield
|
30
|
+
end
|
31
|
+
|
32
|
+
def user(&block)
|
33
|
+
return yield unless options[:user]
|
34
|
+
shell = options[:shell] || 'sh'
|
35
|
+
"sudo -u #{options[:user]} #{environment_string + " " unless environment_string.empty?}-- #{shell} -c '%s'" % %Q{#{yield}}
|
36
|
+
end
|
37
|
+
|
38
|
+
def with(&block)
|
39
|
+
return yield if environment_hash.empty? || sudo_command?
|
40
|
+
"( #{environment_string} %s )" % yield
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def options_env
|
46
|
+
(options[:env] || {}).merge(default_ssh_options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def default_env
|
50
|
+
SSHKit.config.default_env || {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def default_ssh_options
|
54
|
+
ssh_forwarding_required? ? {'SSH_AUTH_SOCK' => '$SSH_AUTH_SOCK'} : {}
|
55
|
+
end
|
56
|
+
|
57
|
+
def ssh_forwarding_required?
|
58
|
+
ssh_command? && sudo_command? && ssh_forwarding_enabled?
|
59
|
+
end
|
60
|
+
|
61
|
+
def ssh_command?
|
62
|
+
options.fetch(:ssh_commands, []).include?(command)
|
63
|
+
end
|
64
|
+
|
65
|
+
def ssh_forwarding_enabled?
|
66
|
+
options[:host] && options[:host].ssh_options[:forward_agent]
|
67
|
+
end
|
68
|
+
|
69
|
+
def sudo_command?
|
70
|
+
options[:user]
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/sshkit/backends/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
|
6
|
+
gem.authors = ["Theo Cushion", "Dennis Ideler"]
|
7
|
+
gem.email = ["tcushion@pivotal.io", "dennis.ideler@fundingcircle.com"]
|
8
|
+
gem.summary = %q{SSHKit backend for globally sudoing commands}
|
9
|
+
gem.description = %q{A backend to be used in conjunction with Capistrano 3
|
10
|
+
and SSHKit to allow deployment on setups where users login as one identity and
|
11
|
+
then need to sudo to a different identity for each command.}
|
12
|
+
gem.homepage = "http://github.com/fundingcircle/sshkit-backends-netssh_global"
|
13
|
+
# gem.license = "GPL3"
|
14
|
+
|
15
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
gem.files = `git ls-files`.split("\n")
|
17
|
+
gem.test_files = `git ls-files -- test/*`.split("\n")
|
18
|
+
gem.name = "sshkit-backends-netssh_global"
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
gem.version = SSHKit::Backends::NetsshGlobal::VERSION
|
21
|
+
|
22
|
+
gem.add_runtime_dependency('sshkit', '1.7.1')
|
23
|
+
|
24
|
+
gem.add_development_dependency('minitest', ['>= 2.11.3', '< 2.12.0'])
|
25
|
+
gem.add_development_dependency('rake')
|
26
|
+
gem.add_development_dependency('turn')
|
27
|
+
gem.add_development_dependency('mocha')
|
28
|
+
end
|
data/test/boxes.json
ADDED
@@ -0,0 +1,300 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
require 'sshkit/backends/netssh_global'
|
5
|
+
|
6
|
+
module SSHKit
|
7
|
+
module Backend
|
8
|
+
class TestNetsshGlobalFunctional < FunctionalTest
|
9
|
+
def setup
|
10
|
+
super
|
11
|
+
NetsshGlobal.configure do |config|
|
12
|
+
config.owner = a_user
|
13
|
+
config.directory = nil
|
14
|
+
config.shell = nil
|
15
|
+
end
|
16
|
+
VagrantWrapper.reset!
|
17
|
+
end
|
18
|
+
|
19
|
+
def a_user
|
20
|
+
a_box.fetch('users').fetch(0)
|
21
|
+
end
|
22
|
+
|
23
|
+
def another_user
|
24
|
+
a_box.fetch('users').fetch(1)
|
25
|
+
end
|
26
|
+
|
27
|
+
def a_box
|
28
|
+
VagrantWrapper.boxes_list.first
|
29
|
+
end
|
30
|
+
|
31
|
+
def a_host
|
32
|
+
VagrantWrapper.hosts['one']
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_capture
|
36
|
+
File.open('/dev/null', 'w') do |dnull|
|
37
|
+
SSHKit.capture_output(dnull) do
|
38
|
+
captured_command_result = nil
|
39
|
+
NetsshGlobal.new(a_host) do
|
40
|
+
captured_command_result = capture(:uname)
|
41
|
+
end.run
|
42
|
+
|
43
|
+
assert captured_command_result
|
44
|
+
assert_match captured_command_result, /Linux|Darwin/
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_ssh_option_merge
|
50
|
+
a_host.ssh_options = { paranoid: true }
|
51
|
+
host_ssh_options = {}
|
52
|
+
SSHKit::Backend::NetsshGlobal.config.ssh_options = { forward_agent: false }
|
53
|
+
NetsshGlobal.new(a_host) do |host|
|
54
|
+
capture(:uname)
|
55
|
+
host_ssh_options = host.ssh_options
|
56
|
+
end.run
|
57
|
+
assert_equal({ forward_agent: false, paranoid: true }, host_ssh_options)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_configure_owner_via_global_config
|
61
|
+
NetsshGlobal.configure do |config|
|
62
|
+
config.owner = a_user
|
63
|
+
end
|
64
|
+
|
65
|
+
output = ''
|
66
|
+
NetsshGlobal.new(a_host) do
|
67
|
+
output = capture :whoami
|
68
|
+
end.run
|
69
|
+
assert_equal a_user, output
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_configure_owner_via_host
|
73
|
+
a_host.properties.owner = another_user
|
74
|
+
|
75
|
+
output = ''
|
76
|
+
NetsshGlobal.new(a_host) do
|
77
|
+
output = capture :whoami
|
78
|
+
end.run
|
79
|
+
assert_equal another_user, output
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_configure_shell_via_global_config
|
83
|
+
NetsshGlobal.configure do |config|
|
84
|
+
config.shell = "csh"
|
85
|
+
end
|
86
|
+
|
87
|
+
running_shell = ''
|
88
|
+
NetsshGlobal.new(a_host) do
|
89
|
+
running_shell = capture :echo, '$shell'
|
90
|
+
end.run
|
91
|
+
|
92
|
+
assert_equal '/bin/csh', running_shell
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_configure_directory_to_nil_has_no_effect
|
96
|
+
NetsshGlobal.configure do |config|
|
97
|
+
config.directory = nil
|
98
|
+
end
|
99
|
+
|
100
|
+
output = ''
|
101
|
+
NetsshGlobal.new(a_host) do
|
102
|
+
output = capture :pwd
|
103
|
+
end.run
|
104
|
+
assert_equal "/home/#{a_host.user}", output
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_configure_directory_via_global_config
|
108
|
+
NetsshGlobal.configure do |config|
|
109
|
+
config.directory = '/tmp'
|
110
|
+
end
|
111
|
+
|
112
|
+
output = ''
|
113
|
+
NetsshGlobal.new(a_host) do
|
114
|
+
output = capture :pwd
|
115
|
+
end.run
|
116
|
+
assert_equal '/tmp', output
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_configure_directory_via_host
|
120
|
+
NetsshGlobal.configure do |config|
|
121
|
+
config.directory = '/usr'
|
122
|
+
end
|
123
|
+
|
124
|
+
a_host.properties.directory = '/tmp'
|
125
|
+
output = ''
|
126
|
+
NetsshGlobal.new(a_host) do
|
127
|
+
output = capture :pwd
|
128
|
+
end.run
|
129
|
+
assert_equal '/tmp', output
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_execute_raises_on_non_zero_exit_status_and_captures_stdout_and_stderr
|
133
|
+
err = assert_raises SSHKit::Command::Failed do
|
134
|
+
NetsshGlobal.new(a_host) do
|
135
|
+
execute :echo, "\"Test capturing stderr\" 1>&2; false"
|
136
|
+
end.run
|
137
|
+
end
|
138
|
+
assert_equal "echo exit status: 1\necho stdout: Nothing written\necho stderr: Test capturing stderr\n", err.message
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_test_does_not_raise_on_non_zero_exit_status
|
142
|
+
NetsshGlobal.new(a_host) do
|
143
|
+
test :false
|
144
|
+
end.run
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_test_executes_as_owner_when_command_contains_no_spaces
|
148
|
+
result = NetsshGlobal.new(a_host) do
|
149
|
+
test 'test', '"$USER" = "owner"'
|
150
|
+
end.run
|
151
|
+
|
152
|
+
assert(result, 'Expected test to execute as "owner", but it did not')
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_test_executes_as_ssh_user_when_command_contains_spaces
|
156
|
+
result = NetsshGlobal.new(a_host) do
|
157
|
+
test 'test "$USER" = "vagrant"'
|
158
|
+
end.run
|
159
|
+
|
160
|
+
assert(result, 'Expected test to execute as "vagrant", but it did not')
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_upload_file
|
164
|
+
file_contents = ""
|
165
|
+
file_owner = nil
|
166
|
+
file_name = File.join("/tmp", SecureRandom.uuid)
|
167
|
+
File.open file_name, 'w+' do |f|
|
168
|
+
f.write 'example_file'
|
169
|
+
end
|
170
|
+
|
171
|
+
NetsshGlobal.new(a_host) do
|
172
|
+
upload!(file_name, file_name)
|
173
|
+
file_contents = capture(:cat, file_name)
|
174
|
+
file_owner = capture(:stat, '-c', '%U', file_name)
|
175
|
+
end.run
|
176
|
+
|
177
|
+
assert_equal 'example_file', file_contents
|
178
|
+
assert_equal a_user, file_owner
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_upload_file_to_folder_owned_by_user
|
182
|
+
dir = File.join('/tmp', SecureRandom.uuid)
|
183
|
+
NetsshGlobal.new(a_host) do
|
184
|
+
execute(:mkdir, dir)
|
185
|
+
end.run
|
186
|
+
|
187
|
+
file_name = SecureRandom.uuid
|
188
|
+
local_file = File.join('/tmp', file_name)
|
189
|
+
File.open local_file, 'w+' do |f|
|
190
|
+
f.write 'example_file'
|
191
|
+
end
|
192
|
+
|
193
|
+
file_contents = ""
|
194
|
+
file_owner = nil
|
195
|
+
remote_file = File.join(dir, file_name)
|
196
|
+
NetsshGlobal.new(a_host) do
|
197
|
+
upload!(local_file, remote_file)
|
198
|
+
file_contents = capture(:cat, remote_file)
|
199
|
+
file_owner = capture(:stat, '-c', '%U', remote_file)
|
200
|
+
end.run
|
201
|
+
|
202
|
+
assert_equal 'example_file', file_contents
|
203
|
+
assert_equal a_user, file_owner
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_upload_file_overtop_of_existing_file
|
207
|
+
file_name = File.join('/tmp', SecureRandom.uuid)
|
208
|
+
File.open file_name, 'w+' do |f|
|
209
|
+
f.write 'example_file'
|
210
|
+
end
|
211
|
+
|
212
|
+
NetsshGlobal.new(a_host) do
|
213
|
+
upload!(file_name, file_name)
|
214
|
+
end.run
|
215
|
+
|
216
|
+
file_contents = ""
|
217
|
+
file_owner = nil
|
218
|
+
NetsshGlobal.new(a_host) do
|
219
|
+
upload!(file_name, file_name)
|
220
|
+
file_contents = capture(:cat, file_name)
|
221
|
+
file_owner = capture(:stat, '-c', '%U', file_name)
|
222
|
+
end.run
|
223
|
+
|
224
|
+
assert_equal 'example_file', file_contents
|
225
|
+
assert_equal a_user, file_owner
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_upload_string_io
|
229
|
+
file_contents = ""
|
230
|
+
file_owner = nil
|
231
|
+
NetsshGlobal.new(a_host) do
|
232
|
+
file_name = File.join("/tmp", SecureRandom.uuid)
|
233
|
+
upload!(StringIO.new('example_io'), file_name)
|
234
|
+
file_contents = download!(file_name)
|
235
|
+
file_owner = capture(:stat, '-c', '%U', file_name)
|
236
|
+
end.run
|
237
|
+
assert_equal "example_io", file_contents
|
238
|
+
assert_equal a_user, file_owner
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_upload_large_file
|
242
|
+
size = 25
|
243
|
+
fills = SecureRandom.random_bytes(1024*1024)
|
244
|
+
file_name = "/tmp/file-#{SecureRandom.uuid}-#{size}.txt"
|
245
|
+
File.open(file_name, 'w') do |f|
|
246
|
+
(size).times {f.write(fills) }
|
247
|
+
end
|
248
|
+
|
249
|
+
file_contents = ""
|
250
|
+
NetsshGlobal.new(a_host) do
|
251
|
+
upload!(file_name, file_name)
|
252
|
+
file_contents = download!(file_name)
|
253
|
+
end.run
|
254
|
+
|
255
|
+
assert_equal File.open(file_name).read, file_contents
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_ssh_forwarded_when_command_is_ssh_command
|
259
|
+
remote_ssh_output = ''
|
260
|
+
local_ssh_output = `ssh-add -l 2>&1`.strip
|
261
|
+
a_host.ssh_options = { forward_agent: true }
|
262
|
+
NetsshGlobal.new(a_host) do |host|
|
263
|
+
remote_ssh_output = capture 'ssh-add', '-l', '2>&1;', 'true'
|
264
|
+
end.run
|
265
|
+
|
266
|
+
assert_equal local_ssh_output, remote_ssh_output
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_ssh_not_forwarded_when_command_is_not_an_ssh_command
|
270
|
+
echo_output = ''
|
271
|
+
|
272
|
+
a_host.ssh_options = { forward_agent: true }
|
273
|
+
a_host.properties.ssh_commands = [:not_echo]
|
274
|
+
NetsshGlobal.new(a_host) do |host|
|
275
|
+
echo_output = capture :echo, '$SSH_AUTH_SOCK'
|
276
|
+
end.run
|
277
|
+
|
278
|
+
assert_match '', echo_output
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_can_configure_ssh_commands
|
282
|
+
echo_output = ''
|
283
|
+
|
284
|
+
a_host.ssh_options = { forward_agent: true }
|
285
|
+
a_host.properties.ssh_commands = [:echo]
|
286
|
+
NetsshGlobal.new(a_host) do |host|
|
287
|
+
echo_output = capture :echo, '$SSH_AUTH_SOCK'
|
288
|
+
end.run
|
289
|
+
|
290
|
+
assert_match /\/tmp\//, echo_output
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_default_ssh_commands
|
294
|
+
ssh_commands = NetsshGlobal.config.ssh_commands
|
295
|
+
|
296
|
+
assert_equal [:ssh, :git, :'ssh-add', :bundle], ssh_commands
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|