kanrisuru 0.19.4 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef72387ee3392fab30d54254e7226e066d943757b686bd1e66fea0fc1bd58181
4
- data.tar.gz: eb829fe3e5d90968c17cfa9922161505f4fbdce4a44da5524f35ad23967c7335
3
+ metadata.gz: 767ab1b59818ddd394ef7f4bb96435e5be43d2bf89c2c4469419f20a8a5f4a0c
4
+ data.tar.gz: 4c370eb4c60270ed707a78606976b391d098c1298de026558c80a543e28d8326
5
5
  SHA512:
6
- metadata.gz: 9e6b315320713f79f5693b6a21269dcadbf6327efae5ab8dc4287165ebfd6f0c05cc221cb351911f669f71b1812ac3a43884ed978ef64422f07a3beab835ec4a
7
- data.tar.gz: 21e425b548076e932aa9770f4a0827e3252b6dba3869e90d219bbf3e70d983fadb87f14b7ed1747f3c4c569c109901e4da708211816573c963c96bd3977bee24
6
+ metadata.gz: 8cacf38cbfc427dfe1c3a1980a8c52e3c004f119b13473380f0eaeeb0eba39c5c495bed0a2a2be37add8b8d148505f6a34ff7f0455b6a6c4c6b71f2e80849c75
7
+ data.tar.gz: fbf05703912544955455f75af13ce799e0a039ee7269e7106bb3e2db9e1882cc2b2d90ee535c85e3bd0f259bffe4cfc4684ef49f97bf76884eaa61e1b8d3bc72
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## Kanrisuru 0.20.0 (February 21, 2022) ##
2
+ * Allow hosts to be connected via proxy host. This is much like using a bastion / jump server.
3
+ * Add integration test cases for proxy host connection.
4
+
1
5
  ## Kanrisuru 0.19.4 (February 19, 2022) ##
2
6
  * Add additional family types to `ss` command.
3
7
 
data/kanrisuru.gemspec CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |gem|
27
27
  gem.add_runtime_dependency 'net-ping', '~> 2.0'
28
28
  gem.add_runtime_dependency 'net-scp', '~> 3.0'
29
29
  gem.add_runtime_dependency 'net-ssh', '~> 6.1'
30
+ gem.add_runtime_dependency 'net-ssh-gateway', '~> 2.0'
30
31
 
31
32
  gem.files = `git ls-files`.split("\n")
32
33
  gem.require_paths = ['lib']
@@ -14,7 +14,7 @@ module Kanrisuru
14
14
  else
15
15
  command.append_flag('--all')
16
16
  end
17
-
17
+
18
18
  execute_shell(command)
19
19
 
20
20
  Kanrisuru::Result.new(command) do |cmd|
@@ -1,18 +1,19 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'ostruct'
3
4
 
4
5
  module Kanrisuru
5
6
  module Core
6
7
  module System
7
8
  module Parser
8
- class Sysctl
9
+ class Sysctl
9
10
  class << self
10
11
  def parse(command)
11
12
  result = {}
12
13
 
13
14
  lines = command.to_a
14
15
  lines.each do |line|
15
- next if line.include?("permission denied on key")
16
+ next if line.include?('permission denied on key')
16
17
 
17
18
  keys, value = parse_line(line)
18
19
  next if Kanrisuru::Util.blank?(value)
@@ -27,7 +28,7 @@ module Kanrisuru
27
28
  def build_struct(hash)
28
29
  struct = Struct.new(*hash.keys).new
29
30
 
30
- hash.keys.each do |key|
31
+ hash.each_key do |key|
31
32
  struct[key] = hash[key].is_a?(Hash) ? build_struct(hash[key]) : hash[key]
32
33
  end
33
34
 
@@ -35,7 +36,7 @@ module Kanrisuru
35
36
  end
36
37
 
37
38
  def merge_recursively(h1, h2)
38
- h1.merge(h2) do |k, v1, v2|
39
+ h1.merge(h2) do |_k, v1, v2|
39
40
  if v1.is_a?(Hash) && v2.is_a?(Hash)
40
41
  merge_recursively(v1, v2)
41
42
  else
@@ -64,7 +65,6 @@ module Kanrisuru
64
65
 
65
66
  [string.split('.').map(&:to_sym), value]
66
67
  end
67
-
68
68
  end
69
69
  end
70
70
  end
@@ -60,9 +60,7 @@ module Kanrisuru
60
60
  end
61
61
 
62
62
  def su(user)
63
- @hosts.each do |_host_addr, host|
64
- host.su(user)
65
- end
63
+ @hosts.each { |_, host| host.su(user) }
66
64
  end
67
65
 
68
66
  def chdir(path = '~')
@@ -70,15 +68,11 @@ module Kanrisuru
70
68
  end
71
69
 
72
70
  def cd(path = '~')
73
- @hosts.each do |_host_addr, host|
74
- host.cd(path)
75
- end
71
+ @hosts.each { |_, host| host.cd(path) }
76
72
  end
77
73
 
78
74
  def disconnect
79
- @hosts.each do |_host_addr, host|
80
- host.disconnect
81
- end
75
+ @hosts.each { |_, host| host.disconnect }
82
76
  end
83
77
 
84
78
  private
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'net/ssh'
4
+ require 'net/ssh/gateway'
4
5
  require 'net/scp'
5
6
  require 'net/ping'
6
7
 
@@ -12,6 +13,8 @@ module Kanrisuru
12
13
  attr_reader :host, :username, :password, :port, :keys
13
14
 
14
15
  def initialize(opts = {})
16
+ @opts = opts
17
+
15
18
  @host = opts[:host]
16
19
  @username = opts[:username]
17
20
  @login_user = @username
@@ -84,7 +87,11 @@ module Kanrisuru
84
87
  end
85
88
 
86
89
  def ssh
87
- @ssh ||= Net::SSH.start(@host, @username, keys: @keys, password: @password, port: @port)
90
+ @ssh ||= init_ssh
91
+ end
92
+
93
+ def proxy
94
+ @proxy ||= init_proxy
88
95
  end
89
96
 
90
97
  def ping?
@@ -110,6 +117,7 @@ module Kanrisuru
110
117
 
111
118
  def disconnect
112
119
  ssh.close
120
+ proxy&.close(ssh.transport.port)
113
121
  end
114
122
 
115
123
  private
@@ -158,6 +166,35 @@ module Kanrisuru
158
166
  end
159
167
  end
160
168
 
169
+ def init_ssh
170
+ if proxy&.active?
171
+ proxy.ssh(@host, @username,
172
+ keys: @keys, password: @password, port: @port)
173
+ else
174
+ Net::SSH.start(@host, @username,
175
+ keys: @keys, password: @password, port: @port)
176
+ end
177
+ end
178
+
179
+ def init_proxy
180
+ return unless @opts[:proxy]
181
+
182
+ proxy = @opts[:proxy]
183
+
184
+ case proxy
185
+ when Hash
186
+ Net::SSH::Gateway.new(proxy[:host], proxy[:username],
187
+ keys: proxy[:keys], password: proxy[:password], port: proxy[:port])
188
+ when Kanrisuru::Remote::Host
189
+ Net::SSH::Gateway.new(proxy.host, proxy.username,
190
+ keys: proxy.keys, password: proxy.password, port: proxy.port)
191
+ when Net::SSH::Gateway
192
+ proxy
193
+ else
194
+ raise ArgumentError, 'Invalid proxy type'
195
+ end
196
+ end
197
+
161
198
  def init_hostname
162
199
  command = Kanrisuru::Command.new('hostname')
163
200
  execute(command)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kanrisuru
4
- VERSION = '0.19.4'
4
+ VERSION = '0.20.0'
5
5
  end
@@ -8,6 +8,15 @@
8
8
  "kernel": "Linux",
9
9
  "home": "/home/ubuntu"
10
10
  },
11
+ {
12
+ "name": "proxy",
13
+ "port": 22,
14
+ "username": "ubuntu",
15
+ "ssh_key": "~/.ssh/id_rsa",
16
+ "hostname": "proxy-host",
17
+ "kernel": "Linux",
18
+ "home": "/home/ubuntu"
19
+ },
11
20
  {
12
21
  "name": "ubuntu",
13
22
  "port": 22,
@@ -20,6 +20,11 @@ class TestHosts
20
20
  hosts(name)
21
21
  end
22
22
 
23
+ def resolve(hostname)
24
+ s = Socket.getaddrinfo(hostname, nil)
25
+ s[0][2]
26
+ end
27
+
23
28
  def spec_dir(host_json)
24
29
  random_string = SecureRandom.hex
25
30
  "#{host_json['home']}/.kanrisuru_spec_files_#{random_string[0..5]}"
@@ -103,7 +103,7 @@ RSpec.shared_examples 'system' do |os_name, host_json, _spec_dir|
103
103
  it 'gets kernel sysctl info' do
104
104
  result = host.sysctl
105
105
  expect(result).to be_success
106
- expect(result).to respond_to :net
106
+ expect(result).to respond_to :net
107
107
  expect(result).to respond_to :kernel
108
108
  expect(result).to respond_to :dev
109
109
 
@@ -24,6 +24,47 @@ RSpec.shared_examples 'host' do |os_name, host_json, _spec_dir|
24
24
  expect(host.hostname).to eq(host_json['hostname'])
25
25
  end
26
26
 
27
+ it 'connects with proxy host' do
28
+ config = TestHosts.host('proxy')
29
+ proxy = Kanrisuru::Remote::Host.new(
30
+ host: config['hostname'],
31
+ username: config['username'],
32
+ keys: [config['ssh_key']]
33
+ )
34
+
35
+ expect(proxy).to be_ping
36
+
37
+ host = Kanrisuru::Remote::Host.new(
38
+ host: TestHosts.resolve(host_json['hostname']),
39
+ username: host_json['username'],
40
+ keys: [host_json['ssh_key']],
41
+ proxy: proxy
42
+ )
43
+
44
+ ## Test instiation
45
+ expect(host.proxy).to be_instance_of(Net::SSH::Gateway)
46
+ expect(host.ssh).to be_instance_of(Net::SSH::Connection::Session)
47
+
48
+ ## Test basic commands
49
+ expect(host.hostname).to eq(host_json['hostname'])
50
+
51
+ host.cd('../')
52
+ expect(host.pwd.path).to eq('/home')
53
+
54
+ expect(host.whoami.user).to eq(host_json['username'])
55
+ host.su 'root'
56
+ expect(host.whoami.user).to eq('root')
57
+
58
+ ## Test download
59
+ src_path = '/etc/hosts'
60
+ result = host.download(src_path)
61
+ expect(result).to be_instance_of(String)
62
+ lines = result.split("\n")
63
+ expect(lines.length).to be >= 1
64
+
65
+ ## Test upload
66
+ end
67
+
27
68
  it 'changes directories' do
28
69
  expect(host.pwd.path).to eq(host_json['home'])
29
70
 
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Kanrisuru::Remote::Host do
4
+ before(:all) do
5
+ StubNetwork.stub!
6
+ end
7
+
8
+ after(:all) do
9
+ StubNetwork.unstub!
10
+ end
11
+
12
+ let(:host) do
13
+ described_class.new(
14
+ host: 'localhost',
15
+ username: 'ubuntu',
16
+ keys: ['id_rsa']
17
+ )
18
+ end
19
+
20
+ it 'responds to methods' do
21
+ expect(host).to respond_to(:remote_user)
22
+ expect(host).to respond_to(:hostname)
23
+ expect(host).to respond_to(:os)
24
+ expect(host).to respond_to(:env)
25
+ expect(host).to respond_to(:template)
26
+ expect(host).to respond_to(:fstab)
27
+ expect(host).to respond_to(:chdir)
28
+ expect(host).to respond_to(:cd)
29
+ expect(host).to respond_to(:cpu)
30
+ expect(host).to respond_to(:memory)
31
+ expect(host).to respond_to(:su)
32
+ expect(host).to respond_to(:file)
33
+ expect(host).to respond_to(:ssh)
34
+ expect(host).to respond_to(:proxy)
35
+ expect(host).to respond_to(:ping?)
36
+ expect(host).to respond_to(:execute)
37
+ expect(host).to respond_to(:execute_shell)
38
+ expect(host).to respond_to(:disconnect)
39
+ end
40
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kanrisuru
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.4
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Mammina
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-19 00:00:00.000000000 Z
11
+ date: 2022-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel_tests
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '6.1'
139
+ - !ruby/object:Gem::Dependency
140
+ name: net-ssh-gateway
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '2.0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '2.0'
139
153
  description: " Kanrisuru helps manage remote servers with objected oriented ruby.
140
154
  \n Results come back as structured data, parsed, prepared and ready.\n"
141
155
  email: ryan@avamia.com
@@ -687,6 +701,7 @@ files:
687
701
  - spec/unit/remote/cpu_spec.rb
688
702
  - spec/unit/remote/env_spec.rb
689
703
  - spec/unit/remote/fstab_spec.rb
704
+ - spec/unit/remote/host_spec.rb
690
705
  - spec/unit/template_spec.rb
691
706
  - spec/unit/util_spec.rb
692
707
  homepage: https://kanrisuru.com