kanrisuru 0.1.0 → 0.2.1

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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +17 -0
  3. data/.rubocop.yml +47 -0
  4. data/.rubocop_todo.yml +0 -0
  5. data/CHANGELOG.md +0 -0
  6. data/Gemfile +2 -5
  7. data/LICENSE.txt +1 -1
  8. data/README.md +143 -7
  9. data/Rakefile +5 -3
  10. data/bin/console +4 -3
  11. data/kanrisuru.gemspec +21 -12
  12. data/lib/kanrisuru.rb +41 -2
  13. data/lib/kanrisuru/command.rb +99 -0
  14. data/lib/kanrisuru/core.rb +53 -0
  15. data/lib/kanrisuru/core/archive.rb +154 -0
  16. data/lib/kanrisuru/core/disk.rb +302 -0
  17. data/lib/kanrisuru/core/file.rb +332 -0
  18. data/lib/kanrisuru/core/find.rb +108 -0
  19. data/lib/kanrisuru/core/group.rb +97 -0
  20. data/lib/kanrisuru/core/ip.rb +1032 -0
  21. data/lib/kanrisuru/core/mount.rb +138 -0
  22. data/lib/kanrisuru/core/path.rb +140 -0
  23. data/lib/kanrisuru/core/socket.rb +168 -0
  24. data/lib/kanrisuru/core/stat.rb +104 -0
  25. data/lib/kanrisuru/core/stream.rb +121 -0
  26. data/lib/kanrisuru/core/system.rb +348 -0
  27. data/lib/kanrisuru/core/transfer.rb +203 -0
  28. data/lib/kanrisuru/core/user.rb +198 -0
  29. data/lib/kanrisuru/logger.rb +8 -0
  30. data/lib/kanrisuru/mode.rb +277 -0
  31. data/lib/kanrisuru/os_package.rb +235 -0
  32. data/lib/kanrisuru/remote.rb +10 -0
  33. data/lib/kanrisuru/remote/cluster.rb +95 -0
  34. data/lib/kanrisuru/remote/cpu.rb +68 -0
  35. data/lib/kanrisuru/remote/env.rb +33 -0
  36. data/lib/kanrisuru/remote/file.rb +354 -0
  37. data/lib/kanrisuru/remote/fstab.rb +412 -0
  38. data/lib/kanrisuru/remote/host.rb +191 -0
  39. data/lib/kanrisuru/remote/memory.rb +19 -0
  40. data/lib/kanrisuru/remote/os.rb +87 -0
  41. data/lib/kanrisuru/result.rb +78 -0
  42. data/lib/kanrisuru/template.rb +32 -0
  43. data/lib/kanrisuru/util.rb +40 -0
  44. data/lib/kanrisuru/util/bits.rb +203 -0
  45. data/lib/kanrisuru/util/fs_mount_opts.rb +655 -0
  46. data/lib/kanrisuru/util/os_family.rb +213 -0
  47. data/lib/kanrisuru/util/signal.rb +161 -0
  48. data/lib/kanrisuru/version.rb +3 -1
  49. data/spec/functional/core/archive_spec.rb +228 -0
  50. data/spec/functional/core/disk_spec.rb +80 -0
  51. data/spec/functional/core/file_spec.rb +341 -0
  52. data/spec/functional/core/find_spec.rb +52 -0
  53. data/spec/functional/core/group_spec.rb +65 -0
  54. data/spec/functional/core/ip_spec.rb +71 -0
  55. data/spec/functional/core/path_spec.rb +93 -0
  56. data/spec/functional/core/socket_spec.rb +31 -0
  57. data/spec/functional/core/stat_spec.rb +98 -0
  58. data/spec/functional/core/stream_spec.rb +99 -0
  59. data/spec/functional/core/system_spec.rb +96 -0
  60. data/spec/functional/core/transfer_spec.rb +108 -0
  61. data/spec/functional/core/user_spec.rb +76 -0
  62. data/spec/functional/os_package_spec.rb +75 -0
  63. data/spec/functional/remote/cluster_spec.rb +45 -0
  64. data/spec/functional/remote/cpu_spec.rb +41 -0
  65. data/spec/functional/remote/env_spec.rb +36 -0
  66. data/spec/functional/remote/fstab_spec.rb +76 -0
  67. data/spec/functional/remote/host_spec.rb +68 -0
  68. data/spec/functional/remote/memory_spec.rb +29 -0
  69. data/spec/functional/remote/os_spec.rb +63 -0
  70. data/spec/functional/remote/remote_file_spec.rb +180 -0
  71. data/spec/helper/test_hosts.rb +68 -0
  72. data/spec/hosts.json +92 -0
  73. data/spec/spec_helper.rb +11 -3
  74. data/spec/unit/fstab_spec.rb +22 -0
  75. data/spec/unit/kanrisuru_spec.rb +9 -0
  76. data/spec/unit/mode_spec.rb +183 -0
  77. data/spec/unit/template_spec.rb +13 -0
  78. data/spec/unit/util_spec.rb +177 -0
  79. data/spec/zz_reboot_spec.rb +46 -0
  80. metadata +136 -13
  81. data/spec/kanrisuru_spec.rb +0 -9
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Kanrisuru::Core::Disk do
6
+ TestHosts.each_os do |os_name|
7
+ context "with #{os_name}" do
8
+ let(:host_json) { TestHosts.host(os_name) }
9
+ let(:host) do
10
+ Kanrisuru::Remote::Host.new(
11
+ host: host_json['hostname'],
12
+ username: host_json['username'],
13
+ keys: [host_json['ssh_key']]
14
+ )
15
+ end
16
+
17
+ after do
18
+ host.disconnect
19
+ end
20
+
21
+ it 'searches detail on block devices' do
22
+ host.su('root')
23
+ result = host.blkid
24
+ expect(result.success?).to eq(true)
25
+
26
+ device = result[0]
27
+ expect(device).to respond_to(
28
+ :name, :label, :type, :uuid,
29
+ :label_fatboot, :part_uuid, :uuid_sub
30
+ )
31
+
32
+ result = host.blkid(uuid: device.uuid)
33
+ expect(result.success?).to eq(true)
34
+ expect(result.data).to eq(device.name)
35
+
36
+ result = host.blkid(device: device.name)
37
+ # puts device.name
38
+ # puts result.inspect
39
+ expect(result.success?).to eq(true)
40
+ expect(result.data).to respond_to(
41
+ :name, :label, :uuid, :type, :uuid_sub, :label_fatboot, :version, :usage,
42
+ :part_uuid, :part_entry_scheme, :part_entry_uuid, :part_entry_type,
43
+ :part_entry_number, :part_entry_offset, :part_entry_size, :part_entry_disk
44
+ )
45
+ end
46
+
47
+ it 'gets details on block devices' do
48
+ result = host.lsblk
49
+ expect(result.data).to be_instance_of(Array)
50
+
51
+ device = result[0]
52
+
53
+ expect(device).to respond_to(
54
+ :name, :maj_dev, :min_dev,
55
+ :removable_device, :readonly_device,
56
+ :owner, :group, :mode,
57
+ :fsize, :type, :mount_point,
58
+ :fs_type, :uuid, :children
59
+ )
60
+ end
61
+
62
+ it 'gets disk usage' do
63
+ result = host.du(path: "#{host_json['home']}/.bashrc")
64
+ expect(result.success?).to eq(true)
65
+ expect(result[0].path).to eq("#{host_json['home']}/.bashrc")
66
+ end
67
+
68
+ it 'gets disk free for system' do
69
+ expect(host.df.data).to be_instance_of(Array)
70
+ expect(host.df(inodes: true).data).to be_instance_of(Array)
71
+ end
72
+
73
+ it 'gets disk usage for path' do
74
+ result = host.df(path: '/')
75
+ expect(result.data).to be_instance_of(Array)
76
+ expect(result[0].mount).to eq('/')
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,341 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Kanrisuru::Core::File do
6
+ TestHosts.each_os do |os_name|
7
+ context "with #{os_name}" do
8
+ before(:all) do
9
+ host_json = TestHosts.host(os_name)
10
+ host = Kanrisuru::Remote::Host.new(
11
+ host: host_json['hostname'],
12
+ username: host_json['username'],
13
+ keys: [host_json['ssh_key']]
14
+ )
15
+
16
+ host.mkdir("#{host_json['home']}/.kanrisuru_spec_files", silent: true)
17
+ host.disconnect
18
+ end
19
+
20
+ let(:host_json) { TestHosts.host(os_name) }
21
+ let(:host) do
22
+ Kanrisuru::Remote::Host.new(
23
+ host: host_json['hostname'],
24
+ username: host_json['username'],
25
+ keys: [host_json['ssh_key']]
26
+ )
27
+ end
28
+
29
+ let(:spec_dir) { "#{host_json['home']}/.kanrisuru_spec_files" }
30
+
31
+ after do
32
+ host.disconnect
33
+ end
34
+
35
+ after(:all) do
36
+ host_json = TestHosts.host(os_name)
37
+ host = Kanrisuru::Remote::Host.new(
38
+ host: host_json['hostname'],
39
+ username: host_json['username'],
40
+ keys: [host_json['ssh_key']]
41
+ )
42
+
43
+ host.rmdir("#{host_json['home']}/.kanrisuru_spec_files")
44
+ host.rmdir("#{host_json['home']}/extract-tar-files") if host.dir?("#{host_json['home']}/extract-tar-files")
45
+ host.disconnect
46
+ end
47
+
48
+ it 'changes file permission flags' do
49
+ host.su('root')
50
+
51
+ path = "#{spec_dir}/test.txt"
52
+ host.touch(path)
53
+
54
+ mode = host.stat(path).mode
55
+
56
+ expect(mode).to be_instance_of(Kanrisuru::Mode)
57
+
58
+ mode.numeric = 0o777
59
+
60
+ mode = host.chmod(path, mode).mode
61
+
62
+ expect(mode).to be_instance_of(Kanrisuru::Mode)
63
+ expect(mode.numeric).to eq('777')
64
+
65
+ mode.symbolic = 'g=r,o=r'
66
+
67
+ mode = host.chmod(path, mode).mode
68
+ expect(mode.symbolic).to eq('-rwxr--r--')
69
+ expect(mode.to_i).to eq(0o744)
70
+ end
71
+
72
+ it 'changes file owner and group' do
73
+ path = "#{spec_dir}/test-owner.txt"
74
+
75
+ host.touch(path)
76
+
77
+ host.su('root')
78
+ result = host.chown(path, owner: host_json['username'], group: host_json['username'])
79
+
80
+ expect(result.user).to eq(host_json['username'])
81
+ expect(result.uid).to eq(1000)
82
+
83
+ case os_name
84
+ when 'opensuse', 'sles'
85
+ expect(result.group).to eq('users')
86
+ expect(result.gid).to eq(100)
87
+ else
88
+ expect(result.group).to eq(host_json['username'])
89
+ expect(result.gid).to eq(1000)
90
+ end
91
+
92
+ host.su('root')
93
+ result = host.chown(path, owner: 'root', group: 'root')
94
+
95
+ expect(result.user).to eq('root')
96
+ expect(result.uid).to eq(0)
97
+ expect(result.group).to eq('root')
98
+ expect(result.gid).to eq(0)
99
+ end
100
+
101
+ it 'touches files' do
102
+ result = host.touch("#{spec_dir}/test-date.txt", date: '2021-01-01')
103
+
104
+ expect(result.success?).to eq(true)
105
+ expect(result[0].last_modified).to be_instance_of(DateTime)
106
+ expect(result[0].last_modified.to_date.to_s).to eq('2021-01-01')
107
+
108
+ paths = ["#{spec_dir}/test1.config", "#{spec_dir}/test2.config", "#{spec_dir}/test3.config"]
109
+ host.touch(paths)
110
+
111
+ realpaths = paths.map do |path|
112
+ host.realpath(path).path
113
+ end
114
+
115
+ result = host.touch(paths)
116
+ expect(result.data).to be_instance_of(Array)
117
+
118
+ current_date = Time.now.to_date.to_s
119
+
120
+ result.each do |item|
121
+ expect(realpaths.include?(item.path)).to eq(true)
122
+ expect(item.user).to eq(host_json['username'])
123
+ expect(item.fsize).to eq(0)
124
+ expect(item.last_modified.to_date.to_s).to eq(current_date)
125
+ expect(item.last_access.to_date.to_s).to eq(current_date)
126
+ expect(item.last_changed.to_date.to_s).to eq(current_date)
127
+ end
128
+ end
129
+
130
+ it 'soft links file' do
131
+ path = "#{spec_dir}/test-file.txt"
132
+
133
+ result_a = host.touch(path)[0]
134
+ expect(result_a.path).to eq(host.realpath(path).path)
135
+
136
+ result_b = host.symlink(path, "#{spec_dir}/test-symlink.txt")
137
+
138
+ expect(host.realpath(result_b.path).path).to eq(result_a.path)
139
+ expect(result_b.file_type).to eq('symbolic link')
140
+ end
141
+
142
+ it 'hard links file' do
143
+ path = "#{spec_dir}/test-file-ln.txt"
144
+ host.touch(path)
145
+
146
+ result_a = host.touch(path)[0]
147
+ result_b = host.link(path, "#{spec_dir}/test-link.txt")
148
+
149
+ expect(result_b.inode).to eq(result_a.inode)
150
+ expect(result_b.file_type).to eq('regular empty file')
151
+
152
+ result = host.find(inode: result_a.inode)
153
+ files = result.map do |item|
154
+ host.realpath(item.path).path
155
+ end
156
+
157
+ expect(files.include?(host.realpath(result_a.path).path)).to eq(true)
158
+ expect(files.include?(host.realpath(result_b.path).path)).to eq(true)
159
+
160
+ ## Can't hard link dir
161
+ expect(host.link(spec_dir.to_s, "#{spec_dir}/tmpb")).to eq(false)
162
+
163
+ host.rm("#{spec_dir}/test-link.txt")
164
+ end
165
+
166
+ it 'creates directory' do
167
+ path = "#{spec_dir}/test-dir/"
168
+ result = host.mkdir(path)
169
+
170
+ expect(result.success?).to eq(true)
171
+ expect(result.path).to eq(path)
172
+
173
+ case os_name
174
+ when 'fedora', 'rhel', 'centos'
175
+ expect(result.mode.numeric).to eq('775')
176
+ else
177
+ expect(result.mode.numeric).to eq('755')
178
+ end
179
+
180
+ expect(result.file_type).to eq('directory')
181
+ expect(result.uid).to eq(1000)
182
+ expect(result.user).to eq(host_json['username'])
183
+
184
+ case os_name
185
+ when 'sles', 'opensuse'
186
+ expect(result.gid).to eq(100)
187
+ expect(result.group).to eq('users')
188
+ else
189
+ expect(result.gid).to eq(1000)
190
+ expect(result.group).to eq(host_json['username'])
191
+ end
192
+
193
+ result = host.ls(path: spec_dir)
194
+ expect(result.success?).to eq(true)
195
+ selected = result.find { |item| item.path == 'test-dir' }
196
+
197
+ expect(selected.path).to eq('test-dir')
198
+ end
199
+
200
+ it 'copies a file' do
201
+ path = "#{spec_dir}/remote-file.txt"
202
+ copied_path = "#{spec_dir}/remote-file-copied.txt"
203
+
204
+ file = host.file(path)
205
+ file.touch
206
+ file.append do |f|
207
+ f << 'Hello'
208
+ f << 'World'
209
+ end
210
+
211
+ result = host.cp(path, copied_path)
212
+ expect(result.success?).to eq(true)
213
+
214
+ result = host.cat(copied_path)
215
+ expect(result.success?).to eq(true)
216
+ expect(result.data).to eq(%w[Hello World])
217
+ end
218
+
219
+ it 'copies directories' do
220
+ path = "#{spec_dir}/remote-dir"
221
+ subdir_path = "#{path}/subdir"
222
+ copied_path = "#{spec_dir}/copied-dir"
223
+
224
+ result = host.mkdir(path)
225
+ expect(result.success?).to eq(true)
226
+
227
+ result = host.mkdir(subdir_path)
228
+ expect(result.success?).to eq(true)
229
+
230
+ file = host.file("#{subdir_path}/test-nested.txt")
231
+ file.touch
232
+ file.append do |f|
233
+ f << 'This is a'
234
+ f << 'test file...'
235
+ end
236
+
237
+ result = host.cp(path, copied_path, recursive: true)
238
+ expect(result.success?).to eq(true)
239
+ end
240
+
241
+ it 'copies with a backup' do
242
+ path = "#{spec_dir}/remote-file-to-backup.txt"
243
+ copied_path = "#{spec_dir}/remote-file-copied-with-backup.txt"
244
+
245
+ file = host.file(path)
246
+ file.touch
247
+ file.append do |f|
248
+ f << 'Hello'
249
+ f << 'World'
250
+ end
251
+
252
+ result = host.cp(path, copied_path)
253
+ expect(result.success?).to eq(true)
254
+
255
+ file.append do |f|
256
+ f << 'New Content'
257
+ end
258
+
259
+ result = host.cp(path, copied_path, backup: true)
260
+ expect(result.success?).to eq(true)
261
+
262
+ result = host.ls(path: spec_dir)
263
+ backup = result.find { |f| f.path == 'remote-file-copied-2.txt~' }
264
+ expect(backup.path).to eq('remote-file-copied-2.txt~')
265
+ end
266
+
267
+ it 'moves files' do
268
+ path = "#{spec_dir}/remote-file-to-move.txt"
269
+ new_path = "#{spec_dir}/remote-file-moved.txt"
270
+
271
+ file = host.file(path)
272
+ file.touch
273
+ file.append do |f|
274
+ f << 'Hello'
275
+ f << 'World'
276
+ end
277
+
278
+ result = host.mv(path, new_path, no_target_directory: true)
279
+ expect(result.success?).to eq(true)
280
+
281
+ result = host.cat(new_path)
282
+ expect(result).to be_success
283
+ expect(result.data).to eq(%w[Hello World])
284
+ end
285
+
286
+ it 'moves files into a folder' do
287
+ paths = ['file1.txt', 'file2.txt', 'file3.txt']
288
+ paths = paths.map { |p| "#{spec_dir}/#{p}" }
289
+ new_dir = "#{spec_dir}/new_dir"
290
+
291
+ result = host.mkdir(new_dir)
292
+ expect(result).to be_success
293
+
294
+ paths.each do |path|
295
+ file = host.file(path)
296
+ file.touch
297
+ file.append do |f|
298
+ f << 'this is a file'
299
+ end
300
+ end
301
+
302
+ result = host.mv(paths, new_dir, target_directory: true)
303
+ expect(result).to be_success
304
+ end
305
+
306
+ it 'moves folders' do
307
+ path = "#{spec_dir}/remote-dir-to-move"
308
+ moved_path = "#{spec_dir}/moved-dir"
309
+
310
+ result = host.mkdir(path)
311
+ expect(result).to be_success
312
+
313
+ result = host.mv(path, moved_path)
314
+ expect(result).to be_success
315
+ end
316
+
317
+ it 'removes file' do
318
+ path = "#{spec_dir}/test-rm-file.txt"
319
+
320
+ result = host.touch(path)[0]
321
+ expect(host.empty_file?(result.path)).to eq(true)
322
+
323
+ result = host.rm(path)
324
+ expect(result.success?).to eq(true)
325
+ expect(host.empty_file?(path)).to eq(false)
326
+ end
327
+
328
+ it 'counts a file' do
329
+ result = host.wc('/etc/hosts')
330
+
331
+ expect(result.success?).to eq(true)
332
+ expect(result).to respond_to(:lines, :words, :characters)
333
+
334
+ lines = result.lines
335
+ result = host.cat('/etc/hosts')
336
+
337
+ expect(lines).to eq(result.to_a.length)
338
+ end
339
+ end
340
+ end
341
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Kanrisuru::Core::Find do
6
+ TestHosts.each_os do |os_name|
7
+ context "with #{os_name}" do
8
+ let(:host_json) { TestHosts.host(os_name) }
9
+ let(:host) do
10
+ Kanrisuru::Remote::Host.new(
11
+ host: host_json['hostname'],
12
+ username: host_json['username'],
13
+ keys: [host_json['ssh_key']]
14
+ )
15
+ end
16
+
17
+ after do
18
+ host.disconnect
19
+ end
20
+
21
+ it 'finds home directory' do
22
+ result = host.find(paths: '/home')
23
+ home = result.find { |item| item.path == host_json['home'] }
24
+ expect(home.path).to eq(host_json['home'])
25
+
26
+ result = host.find(paths: ['/home'])
27
+ home = result.find { |item| item.path == host_json['home'] }
28
+ expect(home.path).to eq(host_json['home'])
29
+ end
30
+
31
+ it 'finds /etc/hosts file' do
32
+ host.su('root')
33
+ result = host.find(paths: '/etc', type: 'file', name: 'hosts', uid: 0, gid: 0, writeable: true, maxdepth: 1)
34
+ expect(result[0].path).to eq('/etc/hosts')
35
+
36
+ file = host.stat(result[0].path)
37
+ expect(file.uid).to eq(0)
38
+ expect(file.gid).to eq(0)
39
+ end
40
+
41
+ it 'finds files with regex' do
42
+ result = host.find(paths: '~', regex: '.*.\\(js\\|rb\\)')
43
+ expect(result.data).to be_instance_of(Array)
44
+ end
45
+
46
+ it 'finds files by size' do
47
+ result = host.find(paths: '~', size: '+2M', type: 'file')
48
+ expect(result.data).to be_instance_of(Array)
49
+ end
50
+ end
51
+ end
52
+ end