sshkit 1.22.1 → 1.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.docker/Dockerfile +6 -0
- data/.docker/ubuntu_setup.sh +22 -0
- data/.github/release-drafter.yml +10 -2
- data/.github/workflows/ci.yml +27 -0
- data/.gitignore +0 -1
- data/.rubocop_todo.yml +0 -7
- data/CONTRIBUTING.md +2 -2
- data/RELEASING.md +1 -1
- data/Rakefile +0 -4
- data/docker-compose.yml +8 -0
- data/lib/sshkit/backends/connection_pool/cache.rb +2 -2
- data/lib/sshkit/backends/netssh/known_hosts.rb +5 -7
- data/lib/sshkit/backends/netssh.rb +0 -1
- data/lib/sshkit/host.rb +18 -0
- data/lib/sshkit/version.rb +1 -1
- data/sshkit.gemspec +0 -1
- data/test/functional/backends/netssh_transfer_tests.rb +1 -1
- data/test/functional/backends/test_netssh.rb +1 -1
- data/test/helper.rb +4 -42
- data/test/support/docker_wrapper.rb +71 -0
- data/test/unit/test_command_map.rb +8 -8
- data/test/unit/test_host.rb +12 -0
- metadata +8 -24
- data/Vagrantfile +0 -24
- data/test/boxes.json +0 -17
- data/test/functional/test_ssh_server_comes_up_for_functional_tests.rb +0 -24
- data/test/support/vagrant_wrapper.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f40ad7a1382ef707a259094c945692f08c44392e0bba7c37fe4099e748301a5e
|
4
|
+
data.tar.gz: 72f3fea395eaaa0036dd701c04692e75c379867465cffaa4ac6cdf1c4f647813
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab28074eba7cb9bdbfcbca9857f5e74fc89ed06acdf872148fcb7329b45754a714c658dacd879fead076de3bbd2541d84bcfd8ef66369007a1444b3edc2b3ac3
|
7
|
+
data.tar.gz: a6d0deb01db101ba2a41dcfcd861a10c7604b17ebe5e25981eebe6d74a0b5c9a9ea345d2dcbb45a4ba30952b571b6736f3bdcd7721d7d8fe684db772cc723700
|
data/.docker/Dockerfile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
export DEBIAN_FRONTEND=noninteractive
|
6
|
+
apt -y update
|
7
|
+
|
8
|
+
# Create `deployer` user that can sudo without a password
|
9
|
+
apt-get -y install sudo
|
10
|
+
adduser --disabled-password deployer < /dev/null
|
11
|
+
echo "deployer:topsecret" | chpasswd
|
12
|
+
echo "deployer ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
13
|
+
|
14
|
+
# Install and configure sshd
|
15
|
+
apt-get -y install openssh-server
|
16
|
+
{
|
17
|
+
echo "Port 22"
|
18
|
+
echo "PasswordAuthentication yes"
|
19
|
+
echo "ChallengeResponseAuthentication no"
|
20
|
+
} >> /etc/ssh/sshd_config
|
21
|
+
mkdir /var/run/sshd
|
22
|
+
chmod 0755 /var/run/sshd
|
data/.github/release-drafter.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
name-template: "$
|
2
|
-
tag-template: "v$
|
1
|
+
name-template: "$RESOLVED_VERSION"
|
2
|
+
tag-template: "v$RESOLVED_VERSION"
|
3
3
|
categories:
|
4
4
|
- title: "⚠️ Breaking Changes"
|
5
5
|
label: "⚠️ Breaking"
|
@@ -11,7 +11,15 @@ categories:
|
|
11
11
|
label: "📚 Docs"
|
12
12
|
- title: "🏠 Housekeeping"
|
13
13
|
label: "🏠 Housekeeping"
|
14
|
+
version-resolver:
|
15
|
+
minor:
|
16
|
+
labels:
|
17
|
+
- "⚠️ Breaking"
|
18
|
+
- "✨ Feature"
|
19
|
+
default: patch
|
14
20
|
change-template: "- $TITLE (#$NUMBER) @$AUTHOR"
|
15
21
|
no-changes-template: "- No changes"
|
16
22
|
template: |
|
17
23
|
$CHANGES
|
24
|
+
|
25
|
+
**Full Changelog:** https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
|
data/.github/workflows/ci.yml
CHANGED
@@ -69,3 +69,30 @@ jobs:
|
|
69
69
|
bundler-cache: true
|
70
70
|
- name: Run rubocop
|
71
71
|
run: bundle exec rake lint
|
72
|
+
|
73
|
+
functional:
|
74
|
+
runs-on: ubuntu-latest
|
75
|
+
strategy:
|
76
|
+
matrix:
|
77
|
+
ruby: ["2.0", "ruby"]
|
78
|
+
steps:
|
79
|
+
- uses: actions/checkout@v4
|
80
|
+
- name: Set up Ruby
|
81
|
+
uses: ruby/setup-ruby@v1
|
82
|
+
with:
|
83
|
+
ruby-version: ${{ matrix.ruby }}
|
84
|
+
bundler-cache: true
|
85
|
+
- name: Run functional tests
|
86
|
+
run: bundle exec rake test:functional
|
87
|
+
|
88
|
+
functional-all:
|
89
|
+
runs-on: ubuntu-latest
|
90
|
+
needs: [functional]
|
91
|
+
if: always()
|
92
|
+
steps:
|
93
|
+
- name: All tests ok
|
94
|
+
if: ${{ !(contains(needs.*.result, 'failure')) }}
|
95
|
+
run: exit 0
|
96
|
+
- name: Some tests failed
|
97
|
+
if: ${{ contains(needs.*.result, 'failure') }}
|
98
|
+
run: exit 1
|
data/.gitignore
CHANGED
data/.rubocop_todo.yml
CHANGED
@@ -102,7 +102,6 @@ Layout/IndentHash:
|
|
102
102
|
Exclude:
|
103
103
|
- 'test/functional/backends/test_local.rb'
|
104
104
|
- 'test/functional/backends/test_netssh.rb'
|
105
|
-
- 'test/support/vagrant_wrapper.rb'
|
106
105
|
- 'test/unit/formatters/test_custom.rb'
|
107
106
|
- 'test/unit/formatters/test_pretty.rb'
|
108
107
|
- 'test/unit/test_mapping_interaction_handler.rb'
|
@@ -445,12 +444,6 @@ Style/MethodName:
|
|
445
444
|
Exclude:
|
446
445
|
- 'test/unit/test_color.rb'
|
447
446
|
|
448
|
-
# Offense count: 1
|
449
|
-
# Cop supports --auto-correct.
|
450
|
-
Style/MutableConstant:
|
451
|
-
Exclude:
|
452
|
-
- 'Vagrantfile'
|
453
|
-
|
454
447
|
# Offense count: 1
|
455
448
|
# Cop supports --auto-correct.
|
456
449
|
# Configuration parameters: Strict.
|
data/CONTRIBUTING.md
CHANGED
@@ -24,8 +24,8 @@ using unsupported features.
|
|
24
24
|
|
25
25
|
## Tests
|
26
26
|
|
27
|
-
SSHKit has a unit test suite and a functional test suite. Some functional tests run
|
28
|
-
[
|
27
|
+
SSHKit has a unit test suite and a functional test suite. Some functional tests run using
|
28
|
+
[Docker](https://docs.docker.com/get-docker/). If possible, you should make sure that the
|
29
29
|
tests pass for each commit by running `rake` in the sshkit directory. This is in case we
|
30
30
|
need to cherry pick commits or rebase. You should ensure the tests pass, (preferably on
|
31
31
|
the minimum and maximum ruby version), before creating a PR.
|
data/RELEASING.md
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
## How to release
|
10
10
|
|
11
11
|
1. Run `bundle install` to make sure that you have all the gems necessary for testing and releasing.
|
12
|
-
2. **Ensure the tests are passing by running `rake test`.** If functional tests fail, ensure you have [
|
12
|
+
2. **Ensure the tests are passing by running `rake test`.** If functional tests fail, ensure you have [Docker installed](https://docs.docker.com/get-docker/) and running.
|
13
13
|
3. Determine which would be the correct next version number according to [semver](http://semver.org/).
|
14
14
|
4. Update the version in `./lib/sshkit/version.rb`.
|
15
15
|
5. Commit the `version.rb` change with a message like "Preparing vX.Y.Z"
|
data/Rakefile
CHANGED
@@ -21,10 +21,6 @@ namespace :test do
|
|
21
21
|
|
22
22
|
end
|
23
23
|
|
24
|
-
Rake::Task["test:functional"].enhance do
|
25
|
-
warn "Remember there are still some VMs running, kill them with `vagrant halt` if you are finished using them."
|
26
|
-
end
|
27
|
-
|
28
24
|
desc 'Run RuboCop lint checks'
|
29
25
|
RuboCop::RakeTask.new(:lint) do |task|
|
30
26
|
task.options = ['--lint']
|
data/docker-compose.yml
ADDED
@@ -36,8 +36,8 @@ class SSHKit::Backend::ConnectionPool::Cache
|
|
36
36
|
def evict
|
37
37
|
# Peek at the first connection to see if it is still fresh. If so, we can
|
38
38
|
# return right away without needing to use `synchronize`.
|
39
|
-
first_expires_at,
|
40
|
-
return if (first_expires_at.nil? || fresh?(first_expires_at))
|
39
|
+
first_expires_at, _first_conn = connections.first
|
40
|
+
return if (first_expires_at.nil? || fresh?(first_expires_at))
|
41
41
|
|
42
42
|
connections.synchronize do
|
43
43
|
fresh, stale = connections.partition do |expires_at, conn|
|
@@ -7,12 +7,11 @@ module SSHKit
|
|
7
7
|
class Netssh < Abstract
|
8
8
|
|
9
9
|
class KnownHostsKeys
|
10
|
-
include Mutex_m
|
11
|
-
|
12
10
|
def initialize(path)
|
13
11
|
super()
|
14
12
|
@path = File.expand_path(path)
|
15
13
|
@hosts_keys = nil
|
14
|
+
@mutex = Mutex.new
|
16
15
|
end
|
17
16
|
|
18
17
|
def keys_for(hostlist)
|
@@ -46,7 +45,7 @@ module SSHKit
|
|
46
45
|
end
|
47
46
|
|
48
47
|
def parse_file
|
49
|
-
synchronize do
|
48
|
+
@mutex.synchronize do
|
50
49
|
return if hosts_keys && hosts_hashes
|
51
50
|
|
52
51
|
unless File.readable?(path)
|
@@ -112,11 +111,10 @@ module SSHKit
|
|
112
111
|
end
|
113
112
|
|
114
113
|
class KnownHosts
|
115
|
-
include Mutex_m
|
116
|
-
|
117
114
|
def initialize
|
118
115
|
super()
|
119
116
|
@files = {}
|
117
|
+
@mutex = Mutex.new
|
120
118
|
end
|
121
119
|
|
122
120
|
def search_for(host, options = {})
|
@@ -128,13 +126,13 @@ module SSHKit
|
|
128
126
|
|
129
127
|
def add(*args)
|
130
128
|
::Net::SSH::KnownHosts.add(*args)
|
131
|
-
synchronize { @files = {} }
|
129
|
+
@mutex.synchronize { @files = {} }
|
132
130
|
end
|
133
131
|
|
134
132
|
private
|
135
133
|
|
136
134
|
def known_hosts_file(path)
|
137
|
-
@files[path] || synchronize { @files[path] ||= KnownHostsKeys.new(path) }
|
135
|
+
@files[path] || @mutex.synchronize { @files[path] ||= KnownHostsKeys.new(path) }
|
138
136
|
end
|
139
137
|
end
|
140
138
|
|
data/lib/sshkit/host.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ostruct'
|
2
|
+
require 'resolv'
|
2
3
|
|
3
4
|
module SSHKit
|
4
5
|
|
@@ -122,6 +123,22 @@ module SSHKit
|
|
122
123
|
|
123
124
|
end
|
124
125
|
|
126
|
+
# @private
|
127
|
+
# :nodoc:
|
128
|
+
class IPv6HostParser < SimpleHostParser
|
129
|
+
def self.suitable?(host_string)
|
130
|
+
host_string.match(Resolv::IPv6::Regex)
|
131
|
+
end
|
132
|
+
|
133
|
+
def port
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
def hostname
|
138
|
+
@host_string.match(Resolv::IPv6::Regex)[0]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
125
142
|
class HostWithPortParser < SimpleHostParser
|
126
143
|
|
127
144
|
def self.suitable?(host_string)
|
@@ -192,6 +209,7 @@ module SSHKit
|
|
192
209
|
|
193
210
|
PARSERS = [
|
194
211
|
SimpleHostParser,
|
212
|
+
IPv6HostParser,
|
195
213
|
HostWithPortParser,
|
196
214
|
HostWithUsernameAndPortParser,
|
197
215
|
IPv6HostWithPortParser,
|
data/lib/sshkit/version.rb
CHANGED
data/sshkit.gemspec
CHANGED
@@ -21,7 +21,6 @@ Gem::Specification.new do |gem|
|
|
21
21
|
gem.version = SSHKit::VERSION
|
22
22
|
|
23
23
|
gem.add_runtime_dependency('base64') if RUBY_VERSION >= "2.4"
|
24
|
-
gem.add_runtime_dependency('mutex_m')
|
25
24
|
gem.add_runtime_dependency('net-ssh', '>= 2.8.0')
|
26
25
|
gem.add_runtime_dependency('net-scp', '>= 1.1.2')
|
27
26
|
gem.add_runtime_dependency('net-sftp', '>= 2.1.2')
|
data/test/helper.rb
CHANGED
@@ -28,51 +28,13 @@ class UnitTest < Minitest::Test
|
|
28
28
|
end
|
29
29
|
|
30
30
|
class FunctionalTest < Minitest::Test
|
31
|
-
|
32
31
|
def setup
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def create_user_with_key(username, password = :secret)
|
41
|
-
username, password = username.to_s, password.to_s
|
42
|
-
|
43
|
-
keys = VagrantWrapper.hosts.collect do |_name, host|
|
44
|
-
Net::SSH.start(host.hostname, host.user, port: host.port, password: host.password) do |ssh|
|
45
|
-
|
46
|
-
# Remove the user, make it again, force-generate a key for him
|
47
|
-
# short keys save us a few microseconds
|
48
|
-
ssh.exec!("sudo userdel -rf #{username}; true") # The `rescue nil` of the shell world
|
49
|
-
ssh.exec!("sudo useradd -m #{username}")
|
50
|
-
ssh.exec!("sudo echo y | ssh-keygen -b 1024 -f #{username} -N ''")
|
51
|
-
ssh.exec!("sudo chown vagrant:vagrant #{username}*")
|
52
|
-
ssh.exec!("sudo echo #{username}:#{password} | chpasswd")
|
32
|
+
require_relative "support/docker_wrapper"
|
33
|
+
return if DockerWrapper.running?
|
53
34
|
|
54
|
-
|
55
|
-
|
56
|
-
ssh.exec!("sudo chown #{username}:#{username} /home/#{username}/.ssh")
|
57
|
-
ssh.exec!("sudo chmod 700 /home/#{username}/.ssh")
|
58
|
-
|
59
|
-
# Move the key to authorized keys and chown and chmod it
|
60
|
-
ssh.exec!("sudo cat #{username}.pub > /home/#{username}/.ssh/authorized_keys")
|
61
|
-
ssh.exec!("sudo chown #{username}:#{username} /home/#{username}/.ssh/authorized_keys")
|
62
|
-
ssh.exec!("sudo chmod 600 /home/#{username}/.ssh/authorized_keys")
|
63
|
-
|
64
|
-
key = ssh.exec!("cat /home/vagrant/#{username}")
|
65
|
-
|
66
|
-
# Clean Up Files
|
67
|
-
ssh.exec!("sudo rm #{username} #{username}.pub")
|
68
|
-
|
69
|
-
key
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
Hash[VagrantWrapper.hosts.collect { |n, _h| n.to_sym }.zip(keys)]
|
35
|
+
DockerWrapper.start
|
36
|
+
DockerWrapper.wait_for_ssh_server
|
74
37
|
end
|
75
|
-
|
76
38
|
end
|
77
39
|
|
78
40
|
#
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "socket"
|
2
|
+
|
3
|
+
Minitest.after_run do
|
4
|
+
DockerWrapper.stop if DockerWrapper.running?
|
5
|
+
end
|
6
|
+
|
7
|
+
module DockerWrapper
|
8
|
+
SSH_SERVER_PORT = 2122
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def host
|
12
|
+
SSHKit::Host.new(
|
13
|
+
user: "deployer",
|
14
|
+
hostname: "localhost",
|
15
|
+
port: SSH_SERVER_PORT,
|
16
|
+
password: "topsecret",
|
17
|
+
ssh_options: host_verify_options
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def running?
|
22
|
+
out, status = run_compose_command("ps --status running", false)
|
23
|
+
status.success? && out.include?("ssh_server")
|
24
|
+
end
|
25
|
+
|
26
|
+
def start
|
27
|
+
run_compose_command("up -d")
|
28
|
+
end
|
29
|
+
|
30
|
+
def stop
|
31
|
+
run_compose_command("down")
|
32
|
+
end
|
33
|
+
|
34
|
+
def wait_for_ssh_server(retries=3)
|
35
|
+
Socket.tcp("localhost", SSH_SERVER_PORT, connect_timeout: 1).close
|
36
|
+
sleep(1)
|
37
|
+
rescue Errno::ECONNREFUSED, Errno::ETIMEDOUT
|
38
|
+
retries -= 1
|
39
|
+
sleep(2) && retry if retries.positive?
|
40
|
+
raise
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def run_compose_command(command, echo=true)
|
46
|
+
$stderr.puts "[docker compose] #{command}" if echo
|
47
|
+
Open3.popen2e("docker compose #{command}") do |stdin, outerr, wait_thread|
|
48
|
+
stdin.close
|
49
|
+
output = Thread.new { capture_stream(outerr, echo) }
|
50
|
+
[output.value, wait_thread.value]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def capture_stream(stream, echo=true)
|
55
|
+
buffer = String.new
|
56
|
+
while (line = stream.gets)
|
57
|
+
buffer << line
|
58
|
+
$stderr.puts("[docker compose] #{line}") if echo
|
59
|
+
end
|
60
|
+
buffer
|
61
|
+
end
|
62
|
+
|
63
|
+
def host_verify_options
|
64
|
+
if Net::SSH::Version::MAJOR >= 5
|
65
|
+
{ verify_host_key: :never }
|
66
|
+
else
|
67
|
+
{ paranoid: false }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -27,26 +27,26 @@ module SSHKit
|
|
27
27
|
|
28
28
|
def test_prefix
|
29
29
|
map = CommandMap.new
|
30
|
-
map.prefix[:rake].push("/home/
|
30
|
+
map.prefix[:rake].push("/home/deployer/.rbenv/bin/rbenv exec")
|
31
31
|
map.prefix[:rake].push("bundle exec")
|
32
32
|
|
33
|
-
assert_equal map[:rake], "/home/
|
33
|
+
assert_equal map[:rake], "/home/deployer/.rbenv/bin/rbenv exec bundle exec rake"
|
34
34
|
end
|
35
35
|
|
36
36
|
def test_prefix_procs
|
37
37
|
map = CommandMap.new
|
38
|
-
map.prefix[:rake].push("/home/
|
38
|
+
map.prefix[:rake].push("/home/deployer/.rbenv/bin/rbenv exec")
|
39
39
|
map.prefix[:rake].push(proc{ "bundle exec" })
|
40
40
|
|
41
|
-
assert_equal map[:rake], "/home/
|
41
|
+
assert_equal map[:rake], "/home/deployer/.rbenv/bin/rbenv exec bundle exec rake"
|
42
42
|
end
|
43
43
|
|
44
44
|
def test_prefix_unshift
|
45
45
|
map = CommandMap.new
|
46
46
|
map.prefix[:rake].push("bundle exec")
|
47
|
-
map.prefix[:rake].unshift("/home/
|
47
|
+
map.prefix[:rake].unshift("/home/deployer/.rbenv/bin/rbenv exec")
|
48
48
|
|
49
|
-
assert_equal map[:rake], "/home/
|
49
|
+
assert_equal map[:rake], "/home/deployer/.rbenv/bin/rbenv exec bundle exec rake"
|
50
50
|
end
|
51
51
|
|
52
52
|
def test_indifferent_setter
|
@@ -59,10 +59,10 @@ module SSHKit
|
|
59
59
|
|
60
60
|
def test_indifferent_prefix
|
61
61
|
map = CommandMap.new
|
62
|
-
map.prefix[:rake].push("/home/
|
62
|
+
map.prefix[:rake].push("/home/deployer/.rbenv/bin/rbenv exec")
|
63
63
|
map.prefix["rake"].push("bundle exec")
|
64
64
|
|
65
|
-
assert_equal map[:rake], "/home/
|
65
|
+
assert_equal map[:rake], "/home/deployer/.rbenv/bin/rbenv exec bundle exec rake"
|
66
66
|
end
|
67
67
|
|
68
68
|
def test_prefix_initialization_is_thread_safe
|
data/test/unit/test_host.rb
CHANGED
@@ -28,6 +28,12 @@ module SSHKit
|
|
28
28
|
assert_equal 'example.com', h.hostname
|
29
29
|
end
|
30
30
|
|
31
|
+
def test_custom_host_with_port
|
32
|
+
h = Host.new 'db:22'
|
33
|
+
assert_equal 22, h.port
|
34
|
+
assert_equal 'db', h.hostname
|
35
|
+
end
|
36
|
+
|
31
37
|
def test_host_with_username
|
32
38
|
h = Host.new 'root@example.com'
|
33
39
|
assert_equal 'root', h.username
|
@@ -50,6 +56,12 @@ module SSHKit
|
|
50
56
|
assert_equal 'localhost', h.hostname
|
51
57
|
end
|
52
58
|
|
59
|
+
def test_ipv6_without_brackets
|
60
|
+
h = Host.new '1fff:0:a88:85a3::ac1f'
|
61
|
+
assert_nil h.port
|
62
|
+
assert_equal '1fff:0:a88:85a3::ac1f', h.hostname
|
63
|
+
end
|
64
|
+
|
53
65
|
def test_does_not_confuse_ipv6_hosts_with_port_specification
|
54
66
|
h = Host.new '[1fff:0:a88:85a3::ac1f]:8001'
|
55
67
|
assert_equal 8001, h.port
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sshkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.23.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Hambley
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-06-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: base64
|
@@ -25,20 +25,6 @@ dependencies:
|
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
|
-
- !ruby/object:Gem::Dependency
|
29
|
-
name: mutex_m
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
31
|
-
requirements:
|
32
|
-
- - ">="
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: '0'
|
35
|
-
type: :runtime
|
36
|
-
prerelease: false
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
38
|
-
requirements:
|
39
|
-
- - ">="
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
version: '0'
|
42
28
|
- !ruby/object:Gem::Dependency
|
43
29
|
name: net-ssh
|
44
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -222,6 +208,8 @@ executables: []
|
|
222
208
|
extensions: []
|
223
209
|
extra_rdoc_files: []
|
224
210
|
files:
|
211
|
+
- ".docker/Dockerfile"
|
212
|
+
- ".docker/ubuntu_setup.sh"
|
225
213
|
- ".github/dependabot.yml"
|
226
214
|
- ".github/release-drafter.yml"
|
227
215
|
- ".github/workflows/ci.yml"
|
@@ -241,7 +229,7 @@ files:
|
|
241
229
|
- README.md
|
242
230
|
- RELEASING.md
|
243
231
|
- Rakefile
|
244
|
-
-
|
232
|
+
- docker-compose.yml
|
245
233
|
- examples/images/example_output.png
|
246
234
|
- examples/images/logo.png
|
247
235
|
- examples/simple_connection.rb
|
@@ -284,18 +272,16 @@ files:
|
|
284
272
|
- lib/sshkit/runners/sequential.rb
|
285
273
|
- lib/sshkit/version.rb
|
286
274
|
- sshkit.gemspec
|
287
|
-
- test/boxes.json
|
288
275
|
- test/functional/backends/netssh_transfer_tests.rb
|
289
276
|
- test/functional/backends/test_local.rb
|
290
277
|
- test/functional/backends/test_netssh.rb
|
291
278
|
- test/functional/backends/test_netssh_scp.rb
|
292
279
|
- test/functional/backends/test_netssh_sftp.rb
|
293
|
-
- test/functional/test_ssh_server_comes_up_for_functional_tests.rb
|
294
280
|
- test/helper.rb
|
295
281
|
- test/known_hosts/github
|
296
282
|
- test/known_hosts/github_hash
|
297
283
|
- test/known_hosts/github_ip
|
298
|
-
- test/support/
|
284
|
+
- test/support/docker_wrapper.rb
|
299
285
|
- test/unit/backends/test_abstract.rb
|
300
286
|
- test/unit/backends/test_connection_pool.rb
|
301
287
|
- test/unit/backends/test_local.rb
|
@@ -338,23 +324,21 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
338
324
|
- !ruby/object:Gem::Version
|
339
325
|
version: '0'
|
340
326
|
requirements: []
|
341
|
-
rubygems_version: 3.5.
|
327
|
+
rubygems_version: 3.5.13
|
342
328
|
signing_key:
|
343
329
|
specification_version: 4
|
344
330
|
summary: SSHKit makes it easy to write structured, testable SSH commands in Ruby
|
345
331
|
test_files:
|
346
|
-
- test/boxes.json
|
347
332
|
- test/functional/backends/netssh_transfer_tests.rb
|
348
333
|
- test/functional/backends/test_local.rb
|
349
334
|
- test/functional/backends/test_netssh.rb
|
350
335
|
- test/functional/backends/test_netssh_scp.rb
|
351
336
|
- test/functional/backends/test_netssh_sftp.rb
|
352
|
-
- test/functional/test_ssh_server_comes_up_for_functional_tests.rb
|
353
337
|
- test/helper.rb
|
354
338
|
- test/known_hosts/github
|
355
339
|
- test/known_hosts/github_hash
|
356
340
|
- test/known_hosts/github_ip
|
357
|
-
- test/support/
|
341
|
+
- test/support/docker_wrapper.rb
|
358
342
|
- test/unit/backends/test_abstract.rb
|
359
343
|
- test/unit/backends/test_connection_pool.rb
|
360
344
|
- test/unit/backends/test_local.rb
|
data/Vagrantfile
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
VAGRANTFILE_API_VERSION = "2"
|
2
|
-
|
3
|
-
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
4
|
-
config.vm.box = 'bento/ubuntu-22.10'
|
5
|
-
|
6
|
-
config.vm.boot_timeout = 600 # seconds
|
7
|
-
config.ssh.insert_key = false
|
8
|
-
config.vm.provision "shell", inline: <<-SHELL
|
9
|
-
echo 'ClientAliveInterval 3' >> /etc/ssh/sshd_config
|
10
|
-
echo 'ClientAliveCountMax 3' >> /etc/ssh/sshd_config
|
11
|
-
echo 'MaxAuthTries 6' >> /etc/ssh/sshd_config
|
12
|
-
service ssh restart
|
13
|
-
SHELL
|
14
|
-
|
15
|
-
json_config_path = File.join("test", "boxes.json")
|
16
|
-
list = File.open(json_config_path).read
|
17
|
-
list = JSON.parse(list)
|
18
|
-
|
19
|
-
list.each do |vm|
|
20
|
-
config.vm.define vm["name"] do |web|
|
21
|
-
web.vm.network "forwarded_port", guest: 22, host: vm["port"]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
data/test/boxes.json
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
module SSHKit
|
4
|
-
|
5
|
-
class TestHost < FunctionalTest
|
6
|
-
|
7
|
-
def host
|
8
|
-
@_host ||= Host.new('')
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_that_it_works
|
12
|
-
assert true
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_creating_a_user_gives_us_back_his_private_key_as_a_string
|
16
|
-
skip 'It is not safe to create an user for non vagrant envs' unless VagrantWrapper.running?
|
17
|
-
keys = create_user_with_key(:peter)
|
18
|
-
assert_equal [:one, :two, :three], keys.keys
|
19
|
-
assert keys.values.all?
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
class VagrantWrapper
|
2
|
-
class << self
|
3
|
-
def hosts
|
4
|
-
@vm_hosts ||= begin
|
5
|
-
result = {}
|
6
|
-
|
7
|
-
boxes = boxes_list
|
8
|
-
|
9
|
-
unless running?
|
10
|
-
boxes.map! do |box|
|
11
|
-
box['user'] = ENV['USER']
|
12
|
-
box['port'] = '22'
|
13
|
-
box
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
boxes.each do |vm|
|
18
|
-
result[vm['name']] = vm_host(vm)
|
19
|
-
end
|
20
|
-
|
21
|
-
result
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def running?
|
26
|
-
@running ||= begin
|
27
|
-
status = `#{vagrant_binary} status`
|
28
|
-
status.include?('running')
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def boxes_list
|
33
|
-
json_config_path = File.join('test', 'boxes.json')
|
34
|
-
boxes = File.open(json_config_path).read
|
35
|
-
JSON.parse(boxes)
|
36
|
-
end
|
37
|
-
|
38
|
-
def vagrant_binary
|
39
|
-
'vagrant'
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def vm_host(vm)
|
45
|
-
host_options = {
|
46
|
-
user: vm['user'] || 'vagrant',
|
47
|
-
hostname: vm['hostname'] || 'localhost',
|
48
|
-
port: vm['port'] || '22',
|
49
|
-
password: vm['password'] || 'vagrant',
|
50
|
-
ssh_options: host_verify_options
|
51
|
-
}
|
52
|
-
|
53
|
-
SSHKit::Host.new(host_options)
|
54
|
-
end
|
55
|
-
|
56
|
-
def host_verify_options
|
57
|
-
if Net::SSH::Version::MAJOR >= 5
|
58
|
-
{ verify_host_key: :never }
|
59
|
-
else
|
60
|
-
{ paranoid: false }
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|