kanrisuru 0.20.0 → 1.0.0.beta1

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: 767ab1b59818ddd394ef7f4bb96435e5be43d2bf89c2c4469419f20a8a5f4a0c
4
- data.tar.gz: 4c370eb4c60270ed707a78606976b391d098c1298de026558c80a543e28d8326
3
+ metadata.gz: 38c3969fd06510c73c0237e611fb1b0acd31dade42489f21b9d118a456e5b834
4
+ data.tar.gz: 604ca2ef34b74dc435aa35ee24853f8f563e42cff6309d6d7d2c6b6437aa7bc3
5
5
  SHA512:
6
- metadata.gz: 8cacf38cbfc427dfe1c3a1980a8c52e3c004f119b13473380f0eaeeb0eba39c5c495bed0a2a2be37add8b8d148505f6a34ff7f0455b6a6c4c6b71f2e80849c75
7
- data.tar.gz: fbf05703912544955455f75af13ce799e0a039ee7269e7106bb3e2db9e1882cc2b2d90ee535c85e3bd0f259bffe4cfc4684ef49f97bf76884eaa61e1b8d3bc72
6
+ metadata.gz: 6ef8d8316b07a088e88a4aad0f5d0bb48419890ba0f00895c2bbae01eb356db246104e095d4e7fe06b91d9cebeaa2c2efe973d3302a40e3eeb4714d3e394dd83
7
+ data.tar.gz: b78410887ec8b5b3e809f4e59934f7c7f6e5d0363ddf9e4a38f436bd42ca0a43de8117f837646edec963c07051f4e546a0705ae2e4581a8971ead44943f22cca
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
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
+
1
7
  ## Kanrisuru 0.20.0 (February 21, 2022) ##
2
8
  * Allow hosts to be connected via proxy host. This is much like using a bastion / jump server.
3
9
  * Add integration test cases for proxy host connection.
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
- Kanrisuru at this point only runs commands sequentially. We plan on creating a parallel run mode in a future release.
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
@@ -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
- hosts = cluster.instance_variable_get(:@hosts)
38
- hosts.map do |host_addr, host|
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
- @hosts.map do |host_addr, host|
49
- { host: host_addr, result: host.send(method_name, *args, &block) }
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,37 +36,23 @@ module Kanrisuru
30
36
  end
31
37
 
32
38
  def execute(command)
33
- @hosts.map do |host_addr, host|
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
- @hosts.map do |host_addr, host|
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
- map_host_results(:hostname)
47
+ map { |host| host.send(:hostname) }
56
48
  end
57
49
 
58
50
  def ping?
59
- map_host_results(:ping?)
51
+ map { |host| host.send(:ping?) }
60
52
  end
61
53
 
62
54
  def su(user)
63
- @hosts.each { |_, host| host.su(user) }
55
+ each { |host| host.su(user) }
64
56
  end
65
57
 
66
58
  def chdir(path = '~')
@@ -68,15 +60,70 @@ module Kanrisuru
68
60
  end
69
61
 
70
62
  def cd(path = '~')
71
- @hosts.each { |_, host| host.cd(path) }
63
+ each { |host| host.cd(path) }
72
64
  end
73
65
 
74
66
  def disconnect
75
- @hosts.each { |_, host| host.disconnect }
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?
76
84
  end
77
85
 
78
86
  private
79
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
+
80
127
  def create_command(command)
81
128
  case command
82
129
  when String
@@ -88,12 +135,6 @@ module Kanrisuru
88
135
  end
89
136
  end
90
137
 
91
- def map_host_results(action)
92
- @hosts.map do |host_addr, host|
93
- { host: host_addr, result: host.send(action) }
94
- end
95
- end
96
-
97
138
  def remove_host(host)
98
139
  if host.instance_of?(Kanrisuru::Remote::Host)
99
140
  removed = false
@@ -119,14 +160,22 @@ module Kanrisuru
119
160
  end
120
161
 
121
162
  def add_host(host_opts)
122
- if host_opts.instance_of?(Hash)
163
+ case host_opts
164
+ when Hash
123
165
  @hosts[host_opts[:host]] = Kanrisuru::Remote::Host.new(host_opts)
124
- elsif host_opts.instance_of?(Kanrisuru::Remote::Host)
166
+ when Kanrisuru::Remote::Host
125
167
  @hosts[host_opts.host] = host_opts
168
+ when Kanrisuru::Remote::Cluster
169
+ host_opts.send(:each_sequential) { |host| @hosts[host.host] = host }
126
170
  else
127
171
  raise ArgumentError, 'Invalid host option'
128
172
  end
129
173
  end
174
+
175
+ def local_concurrency
176
+ ProcessorCount.physical_processor_count
177
+ end
178
+
130
179
  end
131
180
  end
132
181
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kanrisuru
4
- VERSION = '0.20.0'
4
+ VERSION = '1.0.0.beta1'
5
5
  end
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
 
@@ -4,6 +4,8 @@ require 'simplecov'
4
4
  require 'simplecov-cobertura'
5
5
 
6
6
  SimpleCov.start do
7
+ add_filter '/spec/'
8
+
7
9
  command_name "kanrisuru-tests#{ENV['TEST_ENV_NUMBER'] || ''}"
8
10
  merge_timeout 2400
9
11
 
@@ -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
@@ -41,7 +41,7 @@ RSpec.shared_examples 'host' do |os_name, host_json, _spec_dir|
41
41
  proxy: proxy
42
42
  )
43
43
 
44
- ## Test instiation
44
+ ## Test instantiation
45
45
  expect(host.proxy).to be_instance_of(Net::SSH::Gateway)
46
46
  expect(host.ssh).to be_instance_of(Net::SSH::Connection::Session)
47
47
 
@@ -61,8 +61,6 @@ RSpec.shared_examples 'host' do |os_name, host_json, _spec_dir|
61
61
  expect(result).to be_instance_of(String)
62
62
  lines = result.split("\n")
63
63
  expect(lines.length).to be >= 1
64
-
65
- ## Test upload
66
64
  end
67
65
 
68
66
  it 'changes directories' do
@@ -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
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.20.0
4
+ version: 1.0.0.beta1
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-20 00:00:00.000000000 Z
11
+ date: 2022-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parallel_tests
@@ -440,6 +440,7 @@ files:
440
440
  - lib/kanrisuru/os_package/collection.rb
441
441
  - lib/kanrisuru/os_package/define.rb
442
442
  - lib/kanrisuru/os_package/include.rb
443
+ - lib/kanrisuru/processor_count.rb
443
444
  - lib/kanrisuru/remote.rb
444
445
  - lib/kanrisuru/remote/cluster.rb
445
446
  - lib/kanrisuru/remote/cpu.rb
@@ -486,6 +487,7 @@ files:
486
487
  - spec/functional/core/user_spec.rb
487
488
  - spec/functional/core/yum_spec.rb
488
489
  - spec/functional/core/zypper_spec.rb
490
+ - spec/functional/processor_count_spec.rb
489
491
  - spec/functional/remote/cluster_spec.rb
490
492
  - spec/functional/remote/cpu_spec.rb
491
493
  - spec/functional/remote/env_spec.rb
@@ -602,7 +604,7 @@ files:
602
604
  - spec/integration/core/zypper/opensuse_spec.rb
603
605
  - spec/integration/core/zypper/sles_spec.rb
604
606
  - spec/integration/os_package_spec.rb
605
- - spec/integration/remote/cluster/ubuntu_spec.rb
607
+ - spec/integration/remote/cluster/cluster_spec.rb
606
608
  - spec/integration/remote/cpu/centos_spec.rb
607
609
  - spec/integration/remote/cpu/debian_spec.rb
608
610
  - spec/integration/remote/cpu/fedora_spec.rb
@@ -670,7 +672,6 @@ files:
670
672
  - spec/support/shared_examples/integration/core/user.rb
671
673
  - spec/support/shared_examples/integration/core/yum.rb
672
674
  - spec/support/shared_examples/integration/core/zypper.rb
673
- - spec/support/shared_examples/integration/remote/cluster.rb
674
675
  - spec/support/shared_examples/integration/remote/cpu.rb
675
676
  - spec/support/shared_examples/integration/remote/env_spec.rb
676
677
  - spec/support/shared_examples/integration/remote/fstab.rb
@@ -697,6 +698,7 @@ files:
697
698
  - spec/unit/core/zypper_spec.rb
698
699
  - spec/unit/kanrisuru_spec.rb
699
700
  - spec/unit/mode_spec.rb
701
+ - spec/unit/processor_count_spec.rb
700
702
  - spec/unit/remote/cluster_spec.rb
701
703
  - spec/unit/remote/cpu_spec.rb
702
704
  - spec/unit/remote/env_spec.rb
@@ -722,9 +724,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
722
724
  version: 2.5.0
723
725
  required_rubygems_version: !ruby/object:Gem::Requirement
724
726
  requirements:
725
- - - ">="
727
+ - - ">"
726
728
  - !ruby/object:Gem::Version
727
- version: '0'
729
+ version: 1.3.1
728
730
  requirements: []
729
731
  rubygems_version: 3.3.5
730
732
  signing_key:
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- TestHosts.each_os(only: %w[ubuntu]) do |os_name, host_json, spec_dir|
6
- RSpec.describe Kanrisuru::Core::Disk do
7
- include_examples 'disk', os_name, host_json, spec_dir
8
- end
9
- end
@@ -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