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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb8de477e2168c782b7cb082a6a6760fd56aa6925f1820ee80e45baff76a7b27
4
- data.tar.gz: ad21e0b9787a2e42d8626a367f11b44ff97ec27f000a6ec8f7967d7b22da066d
3
+ metadata.gz: 4f5fe692ff53ac4de87ca38181765a63cf88f0beab4e44145c780ba9af934ede
4
+ data.tar.gz: 58acc02d34aff916670ab26c9659f7e40205d31492ec5f043ea51487df33cb62
5
5
  SHA512:
6
- metadata.gz: 0cdeb2cda038612234429eb9ca172f294f60bb8bdcb0d5db2490231dfc4ab4205ae240b3f8ef8ebab41b5de6ef9d2599c7db76dd0ebe229b8b896e3a831c8805
7
- data.tar.gz: b32d4fe02fe5897a8f56d827290516ceb393db63068f9cba3a4396b79e667dd62a332013fbb6fe674cd680ccd374faff877441f92f57048d5b782e244b23ec20
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
@@ -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
- if os_method_cache.key?(method_name)
172
- unbound_method = os_method_cache[method_name]
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kanrisuru
4
- VERSION = '0.7.0'
4
+ VERSION = '0.8.0'
5
5
  end
@@ -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
@@ -4,7 +4,6 @@ require 'simplecov'
4
4
  SimpleCov.start
5
5
 
6
6
  require 'kanrisuru'
7
-
8
7
  require_relative 'helper/test_hosts'
9
8
 
10
9
  Kanrisuru.logger.level = Logger::WARN
@@ -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.7.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-08 00:00:00.000000000 Z
11
+ date: 2021-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec