kanrisuru 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/lib/kanrisuru/core/system.rb +87 -0
- data/lib/kanrisuru/core/zypper.rb +3 -0
- data/lib/kanrisuru/os_package.rb +13 -15
- data/lib/kanrisuru/version.rb +1 -1
- data/spec/functional/core/system_spec.rb +15 -0
- data/spec/functional/core/zypper_spec.rb +6 -0
- data/spec/functional/os_package_spec.rb +94 -0
- data/spec/spec_helper.rb +0 -1
- data/spec/unit/core/system_spec.rb +12 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f5fe692ff53ac4de87ca38181765a63cf88f0beab4e44145c780ba9af934ede
|
4
|
+
data.tar.gz: 58acc02d34aff916670ab26c9659f7e40205d31492ec5f043ea51487df33cb62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2b8134ef2351a86f88286a7ed50a1f768510c75f65ecbf9d9684f376606b46ea023f1b78723ae550183c7606e230d7152614d263b19f1a31c6bf6fe0cfa2cc3
|
7
|
+
data.tar.gz: f7382ab716a20185ec071f96b6793afa7fcc1e11d32a0dd3174455cb7a5ba19d3fb61aa0fbb7d5574f26af36d983b3fae4ee9ec5757f16ef2a21edc43d5d83cd
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## Kanrisuru 0.8.0 (August 18, 2021) ##
|
2
|
+
* Add last / lastb implementation in system core module.
|
3
|
+
|
4
|
+
## Kanrisuru 0.7.3 (August 9, 2021) ##
|
5
|
+
* Fixed bug with zypper remove package, where the package names weren't being added to the linux command.
|
6
|
+
* Test case added to ensure package is removed.
|
7
|
+
|
8
|
+
## Kanrisuru 0.7.2 (August 9, 2021) ##
|
9
|
+
* Fixed bug with the `os_method_cache` instance variable set in the namespaced instance of a host. This was causing collision issues inbetween host instances, where, hosts with the same aliased method name was getting overwritten (with a different OS), since the namespace instance variable existing on the host class definition wasn't getting reset inbetween host instantiations. Given that the `os_method_cache` is normally re-instantiated, this bug fix addresses this so that the `os_method_cache` is always defined on the host instance, ie:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
host.instance_variable_get(:@os_method_cache)
|
13
|
+
host.instance_variable_set(:@os_method_cache, os_method_cache)
|
14
|
+
```
|
15
|
+
This is done instead of being saved on the namespace module. With the previous bug fix of using namespaced keys, there's no way for a method to be overwritten otherwise with a global `os_method_cache`.
|
16
|
+
|
17
|
+
## Kanrisuru 0.7.1 (August 8, 2021) ##
|
18
|
+
* Fix bug with `os_include` when caching namespace unbound methods, use the namespace in the
|
19
|
+
cache key to avoid any namespace collisions with the same method name, namely:
|
20
|
+
```ruby
|
21
|
+
"#{namespace}.#{method_name}"
|
22
|
+
```
|
23
|
+
|
1
24
|
## Kanrisuru 0.7.0 (August 8, 2021) ##
|
2
25
|
* Simplify `FileInfo` struct for return object of `ls` command.
|
3
26
|
* Rename `size` to `fsize` for the `OpenFile` struct to avoid method naming conflicts of the struct class.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'date'
|
4
|
+
require 'ipaddr'
|
4
5
|
|
5
6
|
module Kanrisuru
|
6
7
|
module Core
|
@@ -19,6 +20,7 @@ module Kanrisuru
|
|
19
20
|
os_define :linux, :kstat
|
20
21
|
|
21
22
|
os_define :linux, :lsof
|
23
|
+
os_define :linux, :last
|
22
24
|
|
23
25
|
os_define :linux, :uptime
|
24
26
|
|
@@ -116,6 +118,19 @@ module Kanrisuru
|
|
116
118
|
:name
|
117
119
|
)
|
118
120
|
|
121
|
+
SessionDetail = Struct.new(
|
122
|
+
:tty,
|
123
|
+
:login_at,
|
124
|
+
:logout_at,
|
125
|
+
:ip_address,
|
126
|
+
:success
|
127
|
+
)
|
128
|
+
|
129
|
+
LoginUser = Struct.new(
|
130
|
+
:user,
|
131
|
+
:sessions
|
132
|
+
)
|
133
|
+
|
119
134
|
def load_env
|
120
135
|
command = Kanrisuru::Command.new('env')
|
121
136
|
execute_shell(command)
|
@@ -271,6 +286,65 @@ module Kanrisuru
|
|
271
286
|
Kanrisuru::Result.new(command, &:to_i)
|
272
287
|
end
|
273
288
|
|
289
|
+
def last(opts = {})
|
290
|
+
command =
|
291
|
+
if opts[:failed_attempts]
|
292
|
+
Kanrisuru::Command.new('lastb')
|
293
|
+
else
|
294
|
+
Kanrisuru::Command.new('last')
|
295
|
+
end
|
296
|
+
|
297
|
+
command.append_flag('-i')
|
298
|
+
command.append_flag('-F')
|
299
|
+
command.append_arg('-f', opts[:file])
|
300
|
+
|
301
|
+
## Some systems only use 1 space between user and TTY field
|
302
|
+
## Add an additional space in output formatting for simple parsing
|
303
|
+
## logic.
|
304
|
+
command | "sed 's/ / /'"
|
305
|
+
|
306
|
+
execute_shell(command)
|
307
|
+
|
308
|
+
Kanrisuru::Result.new(command) do |cmd|
|
309
|
+
lines = cmd.to_a
|
310
|
+
|
311
|
+
mapping = {}
|
312
|
+
|
313
|
+
lines.each do |line|
|
314
|
+
next if Kanrisuru::Util.blank?(line)
|
315
|
+
next if line.include?('wtmp') || line.include?('btmp')
|
316
|
+
|
317
|
+
line = line.gsub(' still logged in', '- still logged in') if line.include?('still logged in')
|
318
|
+
|
319
|
+
values = line.split(/\s{2,}/, 4)
|
320
|
+
user = values[0]
|
321
|
+
tty = values[1]
|
322
|
+
ip = IPAddr.new(values[2])
|
323
|
+
|
324
|
+
date_range = values[3]
|
325
|
+
login, logout = date_range.split(' - ')
|
326
|
+
|
327
|
+
login = parse_last_date(login) if login
|
328
|
+
|
329
|
+
logout = parse_last_date(logout) if logout
|
330
|
+
|
331
|
+
detail = SessionDetail.new
|
332
|
+
detail.tty = tty
|
333
|
+
detail.ip_address = ip
|
334
|
+
detail.login_at = login
|
335
|
+
detail.logout_at = logout
|
336
|
+
|
337
|
+
detail.success = !Kanrisuru::Util.present?(opts[:failed_attemps])
|
338
|
+
|
339
|
+
mapping[user] = LoginUser.new(user, []) unless mapping.key?(user)
|
340
|
+
|
341
|
+
mapping[user].sessions << detail
|
342
|
+
end
|
343
|
+
|
344
|
+
mapping.values
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
274
348
|
def ps(opts = {})
|
275
349
|
group = opts[:group]
|
276
350
|
user = opts[:user]
|
@@ -567,6 +641,19 @@ module Kanrisuru
|
|
567
641
|
line.split(char, 2)[1]
|
568
642
|
end
|
569
643
|
|
644
|
+
def parse_last_date(string)
|
645
|
+
tokens = string.split
|
646
|
+
|
647
|
+
return if tokens.length < 4
|
648
|
+
|
649
|
+
month_abbr = tokens[1]
|
650
|
+
day = tokens[2]
|
651
|
+
timestamp = tokens[3]
|
652
|
+
year = tokens[4]
|
653
|
+
|
654
|
+
DateTime.parse("#{day} #{month_abbr} #{year} #{timestamp}")
|
655
|
+
end
|
656
|
+
|
570
657
|
def parse_policy_abbr(value)
|
571
658
|
case value
|
572
659
|
when '-'
|
@@ -714,6 +714,9 @@ module Kanrisuru
|
|
714
714
|
zypper_package_type_opt(command, opts)
|
715
715
|
zypper_solver_opts(command, opts)
|
716
716
|
|
717
|
+
packages = Kanrisuru::Util.string_join_array(opts[:packages], ' ')
|
718
|
+
command << packages
|
719
|
+
|
717
720
|
execute_shell(command)
|
718
721
|
Kanrisuru::Result.new(command)
|
719
722
|
end
|
data/lib/kanrisuru/os_package.rb
CHANGED
@@ -8,7 +8,6 @@ module Kanrisuru
|
|
8
8
|
def self.extended(base)
|
9
9
|
base.instance_variable_set(:@os_method_properties, {})
|
10
10
|
base.instance_variable_set(:@os_methods, Set.new)
|
11
|
-
base.instance_variable_set(:@os_method_cache, {})
|
12
11
|
end
|
13
12
|
|
14
13
|
def os_define(os_name, method_name, options = {})
|
@@ -102,12 +101,6 @@ module Kanrisuru
|
|
102
101
|
include_methods = (public_methods + protected_methods + private_methods).flatten
|
103
102
|
|
104
103
|
include_method_bindings = proc do
|
105
|
-
define_method 'os_method_cache' do
|
106
|
-
@os_method_cache ||= {}
|
107
|
-
end
|
108
|
-
|
109
|
-
private :os_method_cache
|
110
|
-
|
111
104
|
include_methods.each do |method_name|
|
112
105
|
define_method method_name do |*args, &block|
|
113
106
|
unbound_method = mod.instance_method(method_name)
|
@@ -144,10 +137,11 @@ module Kanrisuru
|
|
144
137
|
## defined with the methods added.
|
145
138
|
if Kanrisuru::Remote::Host.instance_variable_defined?("@#{namespace}")
|
146
139
|
namespace_class = Kanrisuru::Remote::Host.const_get(Kanrisuru::Util.camelize(namespace))
|
147
|
-
namespace_instance = instance_variable_get("@#{namespace}")
|
140
|
+
namespace_instance = Kanrisuru::Remote::Host.instance_variable_get("@#{namespace}")
|
148
141
|
else
|
149
142
|
namespace_class = Kanrisuru::Remote::Host.const_set(Kanrisuru::Util.camelize(namespace), Class.new)
|
150
143
|
namespace_instance = Kanrisuru::Remote::Host.instance_variable_set("@#{namespace}", namespace_class.new)
|
144
|
+
|
151
145
|
class_eval do
|
152
146
|
define_method namespace do
|
153
147
|
namespace_instance.instance_variable_set(:@host, self)
|
@@ -168,11 +162,12 @@ module Kanrisuru
|
|
168
162
|
define_method method_name do |*args, &block|
|
169
163
|
unbound_method = nil
|
170
164
|
|
171
|
-
|
172
|
-
|
173
|
-
else
|
174
|
-
host = namespace_instance.instance_variable_get(:@host)
|
165
|
+
host = namespace_instance.instance_variable_get(:@host)
|
166
|
+
os_method_cache = host.instance_variable_get(:@os_method_cache) || {}
|
175
167
|
|
168
|
+
if os_method_cache.key?("#{namespace}.#{method_name}")
|
169
|
+
unbound_method = os_method_cache["#{namespace}.#{method_name}"]
|
170
|
+
else
|
176
171
|
## Find the correct method to resolve based on the OS for the remote host.
|
177
172
|
defined_method_name = host.resolve_os_method_name(os_method_properties, method_name)
|
178
173
|
unless defined_method_name
|
@@ -185,7 +180,8 @@ module Kanrisuru
|
|
185
180
|
|
186
181
|
## Cache the unbound method on this host instance for faster resolution on
|
187
182
|
## the next invocation of this method
|
188
|
-
os_method_cache[method_name] = unbound_method
|
183
|
+
os_method_cache["#{namespace}.#{method_name}"] = unbound_method
|
184
|
+
host.instance_variable_set(:@os_method_cache, os_method_cache)
|
189
185
|
end
|
190
186
|
|
191
187
|
## Bind the method to host instance and
|
@@ -197,11 +193,12 @@ module Kanrisuru
|
|
197
193
|
define_method method_name do |*args, &block|
|
198
194
|
unbound_method = nil
|
199
195
|
|
196
|
+
host = self
|
197
|
+
os_method_cache = host.instance_variable_get(:@os_method_cache) || {}
|
198
|
+
|
200
199
|
if os_method_cache.key?(method_name)
|
201
200
|
unbound_method = os_method_cache[method_name]
|
202
201
|
else
|
203
|
-
host = self
|
204
|
-
|
205
202
|
## Find the correct method to resolve based on the OS for the remote host.
|
206
203
|
defined_method_name = host.resolve_os_method_name(os_method_properties, method_name)
|
207
204
|
raise NoMethodError, "undefined method `#{method_name}' for #{self.class}" unless defined_method_name
|
@@ -213,6 +210,7 @@ module Kanrisuru
|
|
213
210
|
## Cache the unbound method on this host instance for faster resolution on
|
214
211
|
## the next invocation of this method
|
215
212
|
os_method_cache[method_name] = unbound_method
|
213
|
+
host.instance_variable_set(:@os_method_cache, os_method_cache)
|
216
214
|
end
|
217
215
|
|
218
216
|
## Bind the method to host instance and
|
data/lib/kanrisuru/version.rb
CHANGED
@@ -96,6 +96,21 @@ RSpec.describe Kanrisuru::Core::System do
|
|
96
96
|
expect(result.cpus.length).to eq(host.cpu.cores)
|
97
97
|
end
|
98
98
|
|
99
|
+
it 'gets login details' do
|
100
|
+
host.su('root')
|
101
|
+
|
102
|
+
result = host.last
|
103
|
+
expect(result).to be_success
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'gets failed login attempts' do
|
107
|
+
host.su('root')
|
108
|
+
|
109
|
+
result = host.last(failed_attempts: true)
|
110
|
+
puts result.data
|
111
|
+
expect(result).to be_success
|
112
|
+
end
|
113
|
+
|
99
114
|
it 'gets process details' do
|
100
115
|
result = host.ps
|
101
116
|
|
@@ -40,6 +40,12 @@ RSpec.describe Kanrisuru::Core::Zypper do
|
|
40
40
|
expect(result).to be_success
|
41
41
|
end
|
42
42
|
|
43
|
+
it 'removes a package' do
|
44
|
+
host.su('root')
|
45
|
+
result = host.zypper('remove', packages: ['ffmpeg'])
|
46
|
+
expect(result).to be_success
|
47
|
+
end
|
48
|
+
|
43
49
|
it 'lists updates' do
|
44
50
|
result = host.zypper('list-updates')
|
45
51
|
expect(result).to be_success
|
@@ -40,18 +40,66 @@ module Kanrisuru
|
|
40
40
|
a - b
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
module TestAliasNames
|
45
|
+
extend Kanrisuru::OsPackage::Define
|
46
|
+
|
47
|
+
os_define :fedora, :output_fedora, alias: :output
|
48
|
+
os_define :debian, :output_debian, alias: :output
|
49
|
+
os_define :sles, :output_sles, alias: :output
|
50
|
+
|
51
|
+
def output_debian
|
52
|
+
'debian'
|
53
|
+
end
|
54
|
+
|
55
|
+
def output_fedora
|
56
|
+
'fedora'
|
57
|
+
end
|
58
|
+
|
59
|
+
def output_sles
|
60
|
+
'sles'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module TestAliasNamesNamespace
|
65
|
+
extend Kanrisuru::OsPackage::Define
|
66
|
+
|
67
|
+
os_define :fedora, :output_fedora, alias: :output
|
68
|
+
os_define :debian, :output_debian, alias: :output
|
69
|
+
os_define :sles, :output_sles, alias: :output
|
70
|
+
|
71
|
+
def output_debian
|
72
|
+
'debian'
|
73
|
+
end
|
74
|
+
|
75
|
+
def output_fedora
|
76
|
+
'fedora'
|
77
|
+
end
|
78
|
+
|
79
|
+
def output_sles
|
80
|
+
'sles'
|
81
|
+
end
|
82
|
+
end
|
43
83
|
end
|
44
84
|
|
45
85
|
module Kanrisuru
|
46
86
|
module Remote
|
47
87
|
class Host
|
48
88
|
os_include Kanrisuru::TestInclude
|
89
|
+
|
90
|
+
os_include Kanrisuru::TestAliasNames
|
91
|
+
os_include Kanrisuru::TestAliasNamesNamespace, namespace: :alias
|
92
|
+
|
49
93
|
os_include Kanrisuru::TestNamespaceAdditions, namespace: :asdf
|
50
94
|
os_include Kanrisuru::TestNamespace, namespace: :asdf
|
51
95
|
end
|
52
96
|
|
53
97
|
class Cluster
|
54
98
|
os_collection Kanrisuru::TestInclude
|
99
|
+
|
100
|
+
os_collection Kanrisuru::TestAliasNames
|
101
|
+
os_collection Kanrisuru::TestAliasNamesNamespace, namespace: :alias
|
102
|
+
|
55
103
|
os_collection Kanrisuru::TestNamespaceAdditions, namespace: :asdf
|
56
104
|
os_collection Kanrisuru::TestNamespace, namespace: :asdf
|
57
105
|
end
|
@@ -94,6 +142,52 @@ RSpec.describe Kanrisuru::OsPackage do
|
|
94
142
|
expect(cluster.asdf.tester).to be_instance_of(Array)
|
95
143
|
|
96
144
|
host.disconnect
|
145
|
+
host2.disconnect
|
146
|
+
cluster.disconnect
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'includes the correct alias named method' do
|
150
|
+
host1 = Kanrisuru::Remote::Host.new(host: 'ubuntu-host', username: 'ubuntu', keys: ['~/.ssh/id_rsa'])
|
151
|
+
host2 = Kanrisuru::Remote::Host.new(host: 'centos-host', username: 'centos', keys: ['~/.ssh/id_rsa'])
|
152
|
+
host3 = Kanrisuru::Remote::Host.new(host: 'opensuse-host', username: 'opensuse', keys: ['~/.ssh/id_rsa'])
|
153
|
+
|
154
|
+
cluster = Kanrisuru::Remote::Cluster.new([host1, host2, host3])
|
155
|
+
|
156
|
+
expect(host1).to respond_to(:output)
|
157
|
+
expect(host2).to respond_to(:output)
|
158
|
+
expect(host3).to respond_to(:output)
|
159
|
+
expect(host1.output).to eq('debian')
|
160
|
+
expect(host2.output).to eq('fedora')
|
161
|
+
expect(host3.output).to eq('sles')
|
162
|
+
|
163
|
+
expect(cluster).to respond_to(:output)
|
164
|
+
expect(cluster.output).to eq([
|
165
|
+
{ host: 'ubuntu-host', result: 'debian' },
|
166
|
+
{ host: 'centos-host', result: 'fedora' },
|
167
|
+
{ host: 'opensuse-host', result: 'sles' }
|
168
|
+
])
|
169
|
+
|
170
|
+
expect(host1).to respond_to(:alias)
|
171
|
+
expect(host2).to respond_to(:alias)
|
172
|
+
expect(host3).to respond_to(:alias)
|
173
|
+
expect(host1.alias).to respond_to(:output)
|
174
|
+
expect(host2.alias).to respond_to(:output)
|
175
|
+
expect(host3.alias).to respond_to(:output)
|
176
|
+
expect(host1.alias.output).to eq('debian')
|
177
|
+
expect(host2.alias.output).to eq('fedora')
|
178
|
+
expect(host3.alias.output).to eq('sles')
|
179
|
+
|
180
|
+
expect(cluster).to respond_to(:alias)
|
181
|
+
expect(cluster.alias).to respond_to(:output)
|
182
|
+
expect(cluster.alias.output).to eq([
|
183
|
+
{ host: 'ubuntu-host', result: 'debian' },
|
184
|
+
{ host: 'centos-host', result: 'fedora' },
|
185
|
+
{ host: 'opensuse-host', result: 'sles' }
|
186
|
+
])
|
187
|
+
|
188
|
+
host1.disconnect
|
189
|
+
host2.disconnect
|
190
|
+
host3.disconnect
|
97
191
|
cluster.disconnect
|
98
192
|
end
|
99
193
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -86,5 +86,17 @@ RSpec.describe Kanrisuru::Core::System do
|
|
86
86
|
:inode,
|
87
87
|
:name
|
88
88
|
)
|
89
|
+
expect(Kanrisuru::Core::System::SessionDetail.new).to respond_to(
|
90
|
+
:tty,
|
91
|
+
:login_at,
|
92
|
+
:logout_at,
|
93
|
+
:ip_address,
|
94
|
+
:success
|
95
|
+
)
|
96
|
+
|
97
|
+
expect(Kanrisuru::Core::System::LoginUser.new).to respond_to(
|
98
|
+
:user,
|
99
|
+
:sessions
|
100
|
+
)
|
89
101
|
end
|
90
102
|
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: 0.8.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: 2021-08-
|
11
|
+
date: 2021-08-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|