kanrisuru 0.19.4 → 1.0.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 +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +39 -1
- data/kanrisuru.gemspec +1 -0
- data/lib/kanrisuru/core/system/commands/sysctl.rb +1 -1
- data/lib/kanrisuru/core/system/parsers/sysctl.rb +5 -5
- data/lib/kanrisuru/os_package/collection.rb +4 -5
- data/lib/kanrisuru/processor_count.rb +45 -0
- data/lib/kanrisuru/remote/cluster.rb +78 -35
- data/lib/kanrisuru/remote/host.rb +38 -1
- data/lib/kanrisuru/version.rb +1 -1
- data/lib/kanrisuru.rb +1 -0
- data/spec/functional/processor_count_spec.rb +17 -0
- data/spec/functional/remote/cluster_spec.rb +87 -1
- data/spec/helper/hosts.json +9 -0
- data/spec/helper/simplecov.rb +2 -0
- data/spec/helper/test_hosts.rb +5 -0
- data/spec/integration/remote/cluster/cluster_spec.rb +115 -0
- data/spec/support/shared_examples/integration/core/system.rb +1 -1
- data/spec/support/shared_examples/integration/remote/host.rb +39 -0
- data/spec/unit/processor_count_spec.rb +10 -0
- data/spec/unit/remote/cluster_spec.rb +5 -0
- data/spec/unit/remote/host_spec.rb +40 -0
- metadata +21 -4
- data/spec/integration/remote/cluster/ubuntu_spec.rb +0 -9
- data/spec/support/shared_examples/integration/remote/cluster.rb +0 -70
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2c8f6cf4fd27ca458feef7d89dd49617d3e4aba1058b203c297c0206bf5d91f0
|
|
4
|
+
data.tar.gz: c0f03db6bee208f1bcd6ed667f3e50db85e56482ded88023e91efa0025c2a7ad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 004c36ab67130dcb5a2bc8ff3dd60a28a15ef9c48b64a523b6386ee05a656f92f8af9492cc75400b16c5c26006c9ba9134c8605c6b3f87c185a79624ccf5af93
|
|
7
|
+
data.tar.gz: a2c3d25e09d91bc8da26198e9bfffe986270671f6e81ace0f11710a328cada0ac341d5e40d097cf204a93b091d7c3d400c9caf8b160064ca087da9dcdddec4b7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## Kanrisuru 1.0.0.beta1 (February 27, 2022) ##
|
|
2
|
+
* Add parallel mode for cluster. Allows hosts to run commands concurrently, reducing time it takes due to the high I/O blocking nature of the network requests.
|
|
3
|
+
* Add test cases for cluster parallel mode.
|
|
4
|
+
* Clean up methods on cluster class to use map and each methods in a simplified manner.
|
|
5
|
+
* Remove `/spec` dir from codecoverage.
|
|
6
|
+
|
|
7
|
+
## Kanrisuru 0.20.0 (February 21, 2022) ##
|
|
8
|
+
* Allow hosts to be connected via proxy host. This is much like using a bastion / jump server.
|
|
9
|
+
* Add integration test cases for proxy host connection.
|
|
10
|
+
|
|
1
11
|
## Kanrisuru 0.19.4 (February 19, 2022) ##
|
|
2
12
|
* Add additional family types to `ss` command.
|
|
3
13
|
|
data/README.md
CHANGED
|
@@ -54,6 +54,27 @@ host = Kanrisuru::Remote::Host.new(
|
|
|
54
54
|
)
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
#### Connect with a Jump / Bastion Host
|
|
58
|
+
To connect to a host behind a firewall through a jump / bastion host, pass either an instance of another Kanrisuru::Remote::Host, or a hash of host config values
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
proxy = Kanrisuru::Remote::Host.new(
|
|
62
|
+
host: 'proxy-host',
|
|
63
|
+
username: 'ubuntu',
|
|
64
|
+
keys: ['~/.ssh/proxy.pem']
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
host = Kanrisuru::Remote::Host.new(
|
|
68
|
+
host: '1.2.3.4',
|
|
69
|
+
username: 'ubuntu',
|
|
70
|
+
keys: ['~/.ssh/id_rsa'],
|
|
71
|
+
proxy: proxy
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
host.whoami
|
|
75
|
+
'ubuntu'
|
|
76
|
+
```
|
|
77
|
+
|
|
57
78
|
#### run a simple echo command on the remote host
|
|
58
79
|
```ruby
|
|
59
80
|
host.env['VAR'] = 'world'
|
|
@@ -124,7 +145,24 @@ host = Kanrisuru::Remote::Host.new(host: 'remote-host-4', username: 'rhel', keys
|
|
|
124
145
|
cluster << host
|
|
125
146
|
```
|
|
126
147
|
|
|
127
|
-
|
|
148
|
+
#### Run cluster in parallel mode to reduce time waiting on blocking IO
|
|
149
|
+
```ruby
|
|
150
|
+
Benchmark.measure do
|
|
151
|
+
cluster.each do |host|
|
|
152
|
+
puts cluster.pwd
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
# => 0.198980 0.029681 0.228661 ( 5.258496)
|
|
156
|
+
|
|
157
|
+
cluster.parallel = true
|
|
158
|
+
|
|
159
|
+
Benchmark.measure do
|
|
160
|
+
cluster.each do |host|
|
|
161
|
+
puts cluster.pwd
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
# => 0.016478 0.007956 0.024434 ( 0.120066)
|
|
165
|
+
```
|
|
128
166
|
|
|
129
167
|
#### To run across all hosts with a single command, cluster will return a array of result hashes
|
|
130
168
|
```ruby
|
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']
|
|
@@ -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?(
|
|
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.
|
|
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 |
|
|
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
|
|
@@ -34,9 +34,8 @@ module Kanrisuru
|
|
|
34
34
|
os_method_names.each do |method_name|
|
|
35
35
|
define_method method_name do |*args, &block|
|
|
36
36
|
cluster = namespace_instance.instance_variable_get(:@cluster)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{ host: host_addr, result: host.send(namespace).send(method_name, *args, &block) }
|
|
37
|
+
cluster.map do |host|
|
|
38
|
+
host.send(namespace).send(method_name, *args, &block)
|
|
40
39
|
end
|
|
41
40
|
end
|
|
42
41
|
end
|
|
@@ -45,8 +44,8 @@ module Kanrisuru
|
|
|
45
44
|
class_eval do
|
|
46
45
|
os_method_names.each do |method_name|
|
|
47
46
|
define_method method_name do |*args, &block|
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
map do |host|
|
|
48
|
+
host.send(method_name, *args, &block)
|
|
50
49
|
end
|
|
51
50
|
end
|
|
52
51
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'etc'
|
|
3
|
+
|
|
4
|
+
module Kanrisuru
|
|
5
|
+
# https://github.com/grosser/parallel/blob/master/lib/parallel/processor_count.rb
|
|
6
|
+
module ProcessorCount
|
|
7
|
+
# Number of processors seen by the OS, used for process scheduling
|
|
8
|
+
def self.processor_count
|
|
9
|
+
@processor_count ||= Integer(ENV['PARALLEL_PROCESSOR_COUNT'] || Etc.nprocessors)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Number of physical processor cores on the current system.
|
|
13
|
+
def self.physical_processor_count
|
|
14
|
+
@physical_processor_count ||= begin
|
|
15
|
+
ppc =
|
|
16
|
+
case RbConfig::CONFIG["target_os"]
|
|
17
|
+
when /darwin[12]/
|
|
18
|
+
IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
|
|
19
|
+
when /linux/
|
|
20
|
+
cores = {} # unique physical ID / core ID combinations
|
|
21
|
+
phy = 0
|
|
22
|
+
IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
|
|
23
|
+
if ln.start_with?("physical")
|
|
24
|
+
phy = ln[/\d+/]
|
|
25
|
+
elsif ln.start_with?("core")
|
|
26
|
+
cid = "#{phy}:#{ln[/\d+/]}"
|
|
27
|
+
cores[cid] = true unless cores[cid]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
cores.count
|
|
31
|
+
when /mswin|mingw/
|
|
32
|
+
require 'win32ole'
|
|
33
|
+
result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
|
|
34
|
+
"select NumberOfCores from Win32_Processor"
|
|
35
|
+
)
|
|
36
|
+
result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
|
|
37
|
+
else
|
|
38
|
+
processor_count
|
|
39
|
+
end
|
|
40
|
+
# fall back to logical count if physical info is invalid
|
|
41
|
+
ppc > 0 ? ppc : processor_count
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
require 'thread'
|
|
2
3
|
|
|
3
4
|
module Kanrisuru
|
|
4
5
|
module Remote
|
|
@@ -6,7 +7,12 @@ module Kanrisuru
|
|
|
6
7
|
extend OsPackage::Collection
|
|
7
8
|
include Enumerable
|
|
8
9
|
|
|
10
|
+
attr_accessor :parallel, :concurrency
|
|
11
|
+
|
|
9
12
|
def initialize(*hosts)
|
|
13
|
+
@parallel = false
|
|
14
|
+
@concurrency = local_concurrency
|
|
15
|
+
|
|
10
16
|
@hosts = {}
|
|
11
17
|
hosts.each do |host_opts|
|
|
12
18
|
add_host(host_opts)
|
|
@@ -30,39 +36,23 @@ module Kanrisuru
|
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
def execute(command)
|
|
33
|
-
|
|
34
|
-
## Need to evaluate each host independently for the command.
|
|
35
|
-
cmd = create_command(command)
|
|
36
|
-
|
|
37
|
-
{ host: host_addr, result: host.execute(cmd) }
|
|
38
|
-
end
|
|
39
|
+
map { |host| host.execute(create_command(command)) }
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def execute_shell(command)
|
|
42
|
-
|
|
43
|
-
## Need to evaluate each host independently for the command.
|
|
44
|
-
cmd = create_command(command)
|
|
45
|
-
|
|
46
|
-
{ host: host_addr, result: host.execute_shell(cmd) }
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def each(&block)
|
|
51
|
-
@hosts.each { |_host_addr, host| block.call(host) }
|
|
43
|
+
map { |host| host.execute_shell(create_command(command)) }
|
|
52
44
|
end
|
|
53
45
|
|
|
54
46
|
def hostname
|
|
55
|
-
|
|
47
|
+
map { |host| host.send(:hostname) }
|
|
56
48
|
end
|
|
57
49
|
|
|
58
50
|
def ping?
|
|
59
|
-
|
|
51
|
+
map { |host| host.send(:ping?) }
|
|
60
52
|
end
|
|
61
53
|
|
|
62
54
|
def su(user)
|
|
63
|
-
|
|
64
|
-
host.su(user)
|
|
65
|
-
end
|
|
55
|
+
each { |host| host.su(user) }
|
|
66
56
|
end
|
|
67
57
|
|
|
68
58
|
def chdir(path = '~')
|
|
@@ -70,19 +60,70 @@ module Kanrisuru
|
|
|
70
60
|
end
|
|
71
61
|
|
|
72
62
|
def cd(path = '~')
|
|
73
|
-
|
|
74
|
-
host.cd(path)
|
|
75
|
-
end
|
|
63
|
+
each { |host| host.cd(path) }
|
|
76
64
|
end
|
|
77
65
|
|
|
78
66
|
def disconnect
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
67
|
+
each { |host| host.disconnect }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def map(&block)
|
|
71
|
+
parallel? ? each_parallel(preserve: true, &block) : each_sequential(preserve: true, &block)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def each(&block)
|
|
75
|
+
parallel? ? each_parallel(preserve: false, &block) : each_sequential(preserve: false, &block)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def parallel?
|
|
79
|
+
@parallel
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def sequential?
|
|
83
|
+
!parallel?
|
|
82
84
|
end
|
|
83
85
|
|
|
84
86
|
private
|
|
85
87
|
|
|
88
|
+
def each_sequential(opts = {}, &block)
|
|
89
|
+
results = @hosts.map do |host_addr, host|
|
|
90
|
+
{ host: host_addr, result: block.call(host) }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
opts[:preserve] ? results : self
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def each_parallel(opts = {}, &block)
|
|
97
|
+
queue = Queue.new.tap do |q|
|
|
98
|
+
@hosts.each { |_, host| q << host }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
threads = []
|
|
102
|
+
results = []
|
|
103
|
+
mutex = Mutex.new
|
|
104
|
+
|
|
105
|
+
## No need to spawn more threads then number of hosts in cluster
|
|
106
|
+
concurrency = queue.length < @concurrency ? queue.length : @concurrency
|
|
107
|
+
concurrency.times do
|
|
108
|
+
threads << Thread.new do
|
|
109
|
+
loop do
|
|
110
|
+
host = queue.pop(true) rescue Thread.exit
|
|
111
|
+
|
|
112
|
+
begin
|
|
113
|
+
result = block.call(host)
|
|
114
|
+
mutex.synchronize { results.push({ host: host.host, result: result }) }
|
|
115
|
+
rescue Exception => exception
|
|
116
|
+
mutex.synchronize { results.push({ host: host.host, result: exception }) }
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
threads.each(&:join)
|
|
123
|
+
|
|
124
|
+
opts[:preserve] ? results : self
|
|
125
|
+
end
|
|
126
|
+
|
|
86
127
|
def create_command(command)
|
|
87
128
|
case command
|
|
88
129
|
when String
|
|
@@ -94,12 +135,6 @@ module Kanrisuru
|
|
|
94
135
|
end
|
|
95
136
|
end
|
|
96
137
|
|
|
97
|
-
def map_host_results(action)
|
|
98
|
-
@hosts.map do |host_addr, host|
|
|
99
|
-
{ host: host_addr, result: host.send(action) }
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
138
|
def remove_host(host)
|
|
104
139
|
if host.instance_of?(Kanrisuru::Remote::Host)
|
|
105
140
|
removed = false
|
|
@@ -125,14 +160,22 @@ module Kanrisuru
|
|
|
125
160
|
end
|
|
126
161
|
|
|
127
162
|
def add_host(host_opts)
|
|
128
|
-
|
|
163
|
+
case host_opts
|
|
164
|
+
when Hash
|
|
129
165
|
@hosts[host_opts[:host]] = Kanrisuru::Remote::Host.new(host_opts)
|
|
130
|
-
|
|
166
|
+
when Kanrisuru::Remote::Host
|
|
131
167
|
@hosts[host_opts.host] = host_opts
|
|
168
|
+
when Kanrisuru::Remote::Cluster
|
|
169
|
+
host_opts.send(:each_sequential) { |host| @hosts[host.host] = host }
|
|
132
170
|
else
|
|
133
171
|
raise ArgumentError, 'Invalid host option'
|
|
134
172
|
end
|
|
135
173
|
end
|
|
174
|
+
|
|
175
|
+
def local_concurrency
|
|
176
|
+
ProcessorCount.physical_processor_count
|
|
177
|
+
end
|
|
178
|
+
|
|
136
179
|
end
|
|
137
180
|
end
|
|
138
181
|
end
|
|
@@ -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 ||=
|
|
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)
|
data/lib/kanrisuru/version.rb
CHANGED
data/lib/kanrisuru.rb
CHANGED
|
@@ -29,6 +29,7 @@ require_relative 'kanrisuru/util'
|
|
|
29
29
|
require_relative 'kanrisuru/mode'
|
|
30
30
|
require_relative 'kanrisuru/os_package'
|
|
31
31
|
require_relative 'kanrisuru/command'
|
|
32
|
+
require_relative 'kanrisuru/processor_count'
|
|
32
33
|
require_relative 'kanrisuru/remote'
|
|
33
34
|
require_relative 'kanrisuru/result'
|
|
34
35
|
require_relative 'kanrisuru/core'
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Kanrisuru::ProcessorCount do
|
|
6
|
+
it 'gets processor count' do
|
|
7
|
+
expect(described_class.processor_count).to be > 0
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'gets physical processor count' do
|
|
11
|
+
expect(described_class.physical_processor_count).to be > 0
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "is even factor of logical cpus" do
|
|
15
|
+
expect(described_class.processor_count % described_class.physical_processor_count).to be == 0
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -27,6 +27,14 @@ RSpec.describe Kanrisuru::Remote::Cluster do
|
|
|
27
27
|
)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
let(:host3) do
|
|
31
|
+
Kanrisuru::Remote::Host.new(
|
|
32
|
+
host: 'centos-host',
|
|
33
|
+
username: 'centos',
|
|
34
|
+
keys: ['id_rsa']
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
30
38
|
it 'adds host to a cluster' do
|
|
31
39
|
cluster = described_class.new(host1)
|
|
32
40
|
expect(cluster.hosts.length).to eq(1)
|
|
@@ -46,7 +54,7 @@ RSpec.describe Kanrisuru::Remote::Cluster do
|
|
|
46
54
|
username: 'centos',
|
|
47
55
|
keys: ['id_rsa']
|
|
48
56
|
}
|
|
49
|
-
|
|
57
|
+
|
|
50
58
|
expect(cluster.hosts.length).to eq(3)
|
|
51
59
|
expect(cluster.count).to eq(3)
|
|
52
60
|
expect(cluster.count).to eq(3)
|
|
@@ -55,6 +63,19 @@ RSpec.describe Kanrisuru::Remote::Cluster do
|
|
|
55
63
|
expect(cluster.hosts).to include(host2)
|
|
56
64
|
end
|
|
57
65
|
|
|
66
|
+
it 'adds a cluster to another cluster' do
|
|
67
|
+
cluster1 = described_class.new(host1, host2)
|
|
68
|
+
cluster2 = described_class.new(host3)
|
|
69
|
+
|
|
70
|
+
cluster1 << cluster2
|
|
71
|
+
expect(cluster1.hosts.length).to eq(3)
|
|
72
|
+
expect(cluster1.count).to eq(3)
|
|
73
|
+
expect(cluster1.count).to eq(3)
|
|
74
|
+
expect(cluster1['centos-host'].username).to eq('centos')
|
|
75
|
+
expect(cluster1.hosts).to include(host1)
|
|
76
|
+
expect(cluster1.hosts).to include(host2)
|
|
77
|
+
end
|
|
78
|
+
|
|
58
79
|
it 'fails to add host to a cluster' do
|
|
59
80
|
cluster = described_class.new
|
|
60
81
|
expect { cluster << 1 }.to raise_error(ArgumentError)
|
|
@@ -90,6 +111,58 @@ RSpec.describe Kanrisuru::Remote::Cluster do
|
|
|
90
111
|
end.to raise_error(ArgumentError)
|
|
91
112
|
end
|
|
92
113
|
|
|
114
|
+
it 'initializes cluster and is run in sequential mode by default' do
|
|
115
|
+
cluster = described_class.new
|
|
116
|
+
expect(cluster).to be_sequential
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it 'sets cluster to parallel mode' do
|
|
120
|
+
cluster = described_class.new
|
|
121
|
+
cluster.parallel = true
|
|
122
|
+
expect(cluster).to be_parallel
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it 'runs commands on a cluster sequentialy' do
|
|
126
|
+
cluster = described_class.new(host1, host2)
|
|
127
|
+
|
|
128
|
+
expect(cluster).to receive(:each_sequential)
|
|
129
|
+
|
|
130
|
+
command = Kanrisuru::Command.new('pwd')
|
|
131
|
+
cluster.execute(command)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it 'runs commands on a cluster in parallel across hosts' do
|
|
135
|
+
cluster = described_class.new(host1, host2)
|
|
136
|
+
cluster.parallel = true
|
|
137
|
+
|
|
138
|
+
expect(cluster).to receive(:each_parallel)
|
|
139
|
+
|
|
140
|
+
command = Kanrisuru::Command.new('pwd')
|
|
141
|
+
cluster.execute(command)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'gets cluster back from each method' do
|
|
145
|
+
cluster = described_class.new(host1, host2)
|
|
146
|
+
|
|
147
|
+
c = cluster.each { |h| h.su('root') }
|
|
148
|
+
expect(c).to be_instance_of(Kanrisuru::Remote::Cluster)
|
|
149
|
+
expect(c.object_id).to eq(cluster.object_id)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it 'gets results back from map method' do
|
|
153
|
+
cluster = described_class.new(host1, host2)
|
|
154
|
+
|
|
155
|
+
results = cluster.map do |host|
|
|
156
|
+
host.execute('hello')
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
expect(results).to be_instance_of(Array)
|
|
160
|
+
results.each do |result|
|
|
161
|
+
expect(result).to have_key(:host)
|
|
162
|
+
expect(result).to have_key(:result)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
93
166
|
it 'runs execute for a command on a cluster' do
|
|
94
167
|
cluster = described_class.new
|
|
95
168
|
cluster << host1
|
|
@@ -185,6 +258,19 @@ RSpec.describe Kanrisuru::Remote::Cluster do
|
|
|
185
258
|
StubNetwork.unstub_command!(:realpath)
|
|
186
259
|
end
|
|
187
260
|
|
|
261
|
+
it 'raises and catches exception in parallel mode' do
|
|
262
|
+
cluster = described_class.new(host1, host2, host3)
|
|
263
|
+
cluster.parallel = true
|
|
264
|
+
|
|
265
|
+
results = cluster.map do |host|
|
|
266
|
+
raise ArgumentError
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
results.each do |result|
|
|
270
|
+
expect(result[:result]).to be_instance_of(ArgumentError)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
188
274
|
it 'changes current working directory for each host in a cluster' do
|
|
189
275
|
cluster = described_class.new(host1, host2)
|
|
190
276
|
|
data/spec/helper/hosts.json
CHANGED
|
@@ -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,
|
data/spec/helper/simplecov.rb
CHANGED
data/spec/helper/test_hosts.rb
CHANGED
|
@@ -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]}"
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'benchmark'
|
|
4
|
+
require 'spec_helper'
|
|
5
|
+
|
|
6
|
+
RSpec.describe Kanrisuru::Remote::Cluster do
|
|
7
|
+
let(:host1) do
|
|
8
|
+
Kanrisuru::Remote::Host.new(
|
|
9
|
+
host: TestHosts.host('ubuntu')['hostname'],
|
|
10
|
+
username: TestHosts.host('ubuntu')['username'],
|
|
11
|
+
keys: [TestHosts.host('ubuntu')['ssh_key']]
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
let(:host2) do
|
|
16
|
+
Kanrisuru::Remote::Host.new(
|
|
17
|
+
host: TestHosts.host('debian')['hostname'],
|
|
18
|
+
username: TestHosts.host('debian')['username'],
|
|
19
|
+
keys: [TestHosts.host('debian')['ssh_key']]
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
let(:host3) do
|
|
24
|
+
Kanrisuru::Remote::Host.new(
|
|
25
|
+
host: TestHosts.host('centos')['hostname'],
|
|
26
|
+
username: TestHosts.host('centos')['username'],
|
|
27
|
+
keys: [TestHosts.host('centos')['ssh_key']]
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
let(:host4) do
|
|
32
|
+
Kanrisuru::Remote::Host.new(
|
|
33
|
+
host: TestHosts.host('opensuse')['hostname'],
|
|
34
|
+
username: TestHosts.host('opensuse')['username'],
|
|
35
|
+
keys: [TestHosts.host('opensuse')['ssh_key']]
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'gets hostname for cluster' do
|
|
40
|
+
cluster = described_class.new(host1, host2, host3, host4)
|
|
41
|
+
expect(cluster.hostname).to match([
|
|
42
|
+
{ host: 'ubuntu-host', result: 'ubuntu-host' },
|
|
43
|
+
{ host: 'debian-host', result: 'debian-host' },
|
|
44
|
+
{ host: 'centos-host', result: 'centos-host' },
|
|
45
|
+
{ host: 'opensuse-host', result: 'opensuse-host' },
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
cluster.disconnect
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'can ping host cluster' do
|
|
52
|
+
cluster = described_class.new(host1, host2, host3, host4)
|
|
53
|
+
expect(cluster.ping?).to match([
|
|
54
|
+
{ host: 'ubuntu-host', result: true },
|
|
55
|
+
{ host: 'debian-host', result: true },
|
|
56
|
+
{ host: 'centos-host', result: true },
|
|
57
|
+
{ host: 'opensuse-host', result: true },
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
cluster.disconnect
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'should use specific number of threads as number of hosts' do
|
|
64
|
+
cluster = described_class.new(host1, host2, host3, host4)
|
|
65
|
+
cluster.parallel = true
|
|
66
|
+
|
|
67
|
+
## Called x2 b/c two methods invoke the parallel runner
|
|
68
|
+
expect(Thread).to receive(:new).exactly(cluster.count * 2).times.and_call_original
|
|
69
|
+
|
|
70
|
+
cluster.hostname
|
|
71
|
+
cluster.disconnect
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'should respect concurrency setting' do
|
|
75
|
+
concurrency = 2
|
|
76
|
+
|
|
77
|
+
cluster = described_class.new(host1, host2, host3, host4)
|
|
78
|
+
cluster.parallel = true
|
|
79
|
+
cluster.concurrency = concurrency
|
|
80
|
+
|
|
81
|
+
## Called x2 b/c two methods invoke the parallel runner
|
|
82
|
+
expect(Thread).to receive(:new).exactly(concurrency * 2).times.and_call_original
|
|
83
|
+
|
|
84
|
+
cluster.hostname
|
|
85
|
+
cluster.disconnect
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'saves time running cluster in parallel mode' do
|
|
89
|
+
cluster = described_class.new(host1, host2, host3, host4)
|
|
90
|
+
time1 = Benchmark.measure {
|
|
91
|
+
cluster.each do |host|
|
|
92
|
+
expect(host.pwd).to be_success
|
|
93
|
+
end
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
cluster.parallel = true
|
|
97
|
+
time2 = Benchmark.measure {
|
|
98
|
+
cluster.each do |host|
|
|
99
|
+
expect(host.pwd).to be_success
|
|
100
|
+
end
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
expect(time1.total).to be > time2.total
|
|
104
|
+
cluster.disconnect
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'disconnects all hosts' do
|
|
108
|
+
cluster = described_class.new(host1, host2, host3, host4)
|
|
109
|
+
cluster.disconnect
|
|
110
|
+
|
|
111
|
+
cluster.each do |host|
|
|
112
|
+
expect(host.ssh).to be_closed
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -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,45 @@ 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 instantiation
|
|
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
|
+
end
|
|
65
|
+
|
|
27
66
|
it 'changes directories' do
|
|
28
67
|
expect(host.pwd.path).to eq(host_json['home'])
|
|
29
68
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Kanrisuru::ProcessorCount do
|
|
6
|
+
it 'responds to methods' do
|
|
7
|
+
expect(described_class).to respond_to(:processor_count)
|
|
8
|
+
expect(described_class).to respond_to(:physical_processor_count)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -26,11 +26,16 @@ RSpec.describe Kanrisuru::Remote::Cluster do
|
|
|
26
26
|
expect(cluster).to respond_to(:execute)
|
|
27
27
|
expect(cluster).to respond_to(:execute_shell)
|
|
28
28
|
expect(cluster).to respond_to(:each)
|
|
29
|
+
expect(cluster).to respond_to(:map)
|
|
29
30
|
expect(cluster).to respond_to(:hostname)
|
|
30
31
|
expect(cluster).to respond_to(:ping?)
|
|
31
32
|
expect(cluster).to respond_to(:su)
|
|
32
33
|
expect(cluster).to respond_to(:chdir)
|
|
33
34
|
expect(cluster).to respond_to(:cd)
|
|
34
35
|
expect(cluster).to respond_to(:disconnect)
|
|
36
|
+
expect(cluster).to respond_to(:parallel)
|
|
37
|
+
expect(cluster).to respond_to(:concurrency)
|
|
38
|
+
expect(cluster).to respond_to(:parallel?)
|
|
39
|
+
expect(cluster).to respond_to(:sequential?)
|
|
35
40
|
end
|
|
36
41
|
end
|
|
@@ -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.
|
|
4
|
+
version: 1.0.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-
|
|
11
|
+
date: 2022-04-27 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
|
|
@@ -426,6 +440,7 @@ files:
|
|
|
426
440
|
- lib/kanrisuru/os_package/collection.rb
|
|
427
441
|
- lib/kanrisuru/os_package/define.rb
|
|
428
442
|
- lib/kanrisuru/os_package/include.rb
|
|
443
|
+
- lib/kanrisuru/processor_count.rb
|
|
429
444
|
- lib/kanrisuru/remote.rb
|
|
430
445
|
- lib/kanrisuru/remote/cluster.rb
|
|
431
446
|
- lib/kanrisuru/remote/cpu.rb
|
|
@@ -472,6 +487,7 @@ files:
|
|
|
472
487
|
- spec/functional/core/user_spec.rb
|
|
473
488
|
- spec/functional/core/yum_spec.rb
|
|
474
489
|
- spec/functional/core/zypper_spec.rb
|
|
490
|
+
- spec/functional/processor_count_spec.rb
|
|
475
491
|
- spec/functional/remote/cluster_spec.rb
|
|
476
492
|
- spec/functional/remote/cpu_spec.rb
|
|
477
493
|
- spec/functional/remote/env_spec.rb
|
|
@@ -588,7 +604,7 @@ files:
|
|
|
588
604
|
- spec/integration/core/zypper/opensuse_spec.rb
|
|
589
605
|
- spec/integration/core/zypper/sles_spec.rb
|
|
590
606
|
- spec/integration/os_package_spec.rb
|
|
591
|
-
- spec/integration/remote/cluster/
|
|
607
|
+
- spec/integration/remote/cluster/cluster_spec.rb
|
|
592
608
|
- spec/integration/remote/cpu/centos_spec.rb
|
|
593
609
|
- spec/integration/remote/cpu/debian_spec.rb
|
|
594
610
|
- spec/integration/remote/cpu/fedora_spec.rb
|
|
@@ -656,7 +672,6 @@ files:
|
|
|
656
672
|
- spec/support/shared_examples/integration/core/user.rb
|
|
657
673
|
- spec/support/shared_examples/integration/core/yum.rb
|
|
658
674
|
- spec/support/shared_examples/integration/core/zypper.rb
|
|
659
|
-
- spec/support/shared_examples/integration/remote/cluster.rb
|
|
660
675
|
- spec/support/shared_examples/integration/remote/cpu.rb
|
|
661
676
|
- spec/support/shared_examples/integration/remote/env_spec.rb
|
|
662
677
|
- spec/support/shared_examples/integration/remote/fstab.rb
|
|
@@ -683,10 +698,12 @@ files:
|
|
|
683
698
|
- spec/unit/core/zypper_spec.rb
|
|
684
699
|
- spec/unit/kanrisuru_spec.rb
|
|
685
700
|
- spec/unit/mode_spec.rb
|
|
701
|
+
- spec/unit/processor_count_spec.rb
|
|
686
702
|
- spec/unit/remote/cluster_spec.rb
|
|
687
703
|
- spec/unit/remote/cpu_spec.rb
|
|
688
704
|
- spec/unit/remote/env_spec.rb
|
|
689
705
|
- spec/unit/remote/fstab_spec.rb
|
|
706
|
+
- spec/unit/remote/host_spec.rb
|
|
690
707
|
- spec/unit/template_spec.rb
|
|
691
708
|
- spec/unit/util_spec.rb
|
|
692
709
|
homepage: https://kanrisuru.com
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
RSpec.shared_examples 'cluster' do |os_name, host_json, _spec_dir|
|
|
6
|
-
context "with #{os_name}" do
|
|
7
|
-
let(:host1) do
|
|
8
|
-
Kanrisuru::Remote::Host.new(
|
|
9
|
-
host: host_json['hostname'],
|
|
10
|
-
username: host_json['username'],
|
|
11
|
-
keys: [host_json['ssh_key']]
|
|
12
|
-
)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
let(:host2) do
|
|
16
|
-
Kanrisuru::Remote::Host.new(
|
|
17
|
-
host: 'localhost',
|
|
18
|
-
username: 'ubuntu',
|
|
19
|
-
keys: ['~/.ssh/id_rsa']
|
|
20
|
-
)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it 'gets hostname for cluster' do
|
|
24
|
-
cluster = described_class.new({
|
|
25
|
-
host: 'localhost',
|
|
26
|
-
username: 'ubuntu',
|
|
27
|
-
keys: ['~/.ssh/id_rsa']
|
|
28
|
-
}, {
|
|
29
|
-
host: '127.0.0.1',
|
|
30
|
-
username: 'ubuntu',
|
|
31
|
-
keys: ['~/.ssh/id_rsa']
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
expect(cluster.hostname).to match([
|
|
35
|
-
{ host: 'localhost', result: 'ubuntu' },
|
|
36
|
-
{ host: '127.0.0.1', result: 'ubuntu' }
|
|
37
|
-
])
|
|
38
|
-
|
|
39
|
-
cluster.disconnect
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it 'can ping host cluster' do
|
|
43
|
-
cluster = described_class.new({
|
|
44
|
-
host: 'localhost',
|
|
45
|
-
username: 'ubuntu',
|
|
46
|
-
keys: ['~/.ssh/id_rsa']
|
|
47
|
-
}, {
|
|
48
|
-
host: '127.0.0.1',
|
|
49
|
-
username: 'ubuntu',
|
|
50
|
-
keys: ['~/.ssh/id_rsa']
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
expect(cluster.ping?).to match([
|
|
54
|
-
{ host: 'localhost', result: true },
|
|
55
|
-
{ host: '127.0.0.1', result: true }
|
|
56
|
-
])
|
|
57
|
-
|
|
58
|
-
cluster.disconnect
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
it 'disconnects all hosts' do
|
|
62
|
-
cluster = described_class.new(host1, host2)
|
|
63
|
-
cluster.disconnect
|
|
64
|
-
|
|
65
|
-
cluster.each do |host|
|
|
66
|
-
expect(host.ssh.closed).to be_truthy
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|