kanrisuru 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'core/path'
4
+ require_relative 'core/system'
5
+ require_relative 'core/disk'
6
+ require_relative 'core/mount'
7
+ require_relative 'core/stat'
8
+ require_relative 'core/find'
9
+ require_relative 'core/file'
10
+ require_relative 'core/group'
11
+ require_relative 'core/user'
12
+ require_relative 'core/archive'
13
+ require_relative 'core/stream'
14
+ require_relative 'core/transfer'
15
+ require_relative 'core/ip'
16
+ require_relative 'core/socket'
17
+
18
+ module Kanrisuru
19
+ module Remote
20
+ class Host
21
+ os_include Kanrisuru::Core::Path
22
+ os_include Kanrisuru::Core::System
23
+ os_include Kanrisuru::Core::Disk
24
+ os_include Kanrisuru::Core::Mount
25
+ os_include Kanrisuru::Core::Stat
26
+ os_include Kanrisuru::Core::Find
27
+ os_include Kanrisuru::Core::File
28
+ os_include Kanrisuru::Core::Group
29
+ os_include Kanrisuru::Core::User
30
+ os_include Kanrisuru::Core::Archive
31
+ os_include Kanrisuru::Core::Stream
32
+ os_include Kanrisuru::Core::Transfer
33
+ os_include Kanrisuru::Core::IP
34
+ os_include Kanrisuru::Core::Socket
35
+ end
36
+
37
+ class Cluster
38
+ os_collection Kanrisuru::Core::Path
39
+ os_collection Kanrisuru::Core::System
40
+ os_collection Kanrisuru::Core::Disk
41
+ os_collection Kanrisuru::Core::Mount
42
+ os_collection Kanrisuru::Core::Stat
43
+ os_collection Kanrisuru::Core::File
44
+ os_collection Kanrisuru::Core::Group
45
+ os_collection Kanrisuru::Core::User
46
+ os_collection Kanrisuru::Core::Archive
47
+ os_collection Kanrisuru::Core::Stream
48
+ os_collection Kanrisuru::Core::Transfer
49
+ os_collection Kanrisuru::Core::IP
50
+ os_collection Kanrisuru::Core::Socket
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ module Core
5
+ module Archive
6
+ extend OsPackage::Define
7
+
8
+ os_define :linux, :tar
9
+
10
+ FilePath = Struct.new(:path)
11
+
12
+ def tar(action, file, opts = {})
13
+ compress = opts[:compress]
14
+ paths = opts[:paths]
15
+ exclude = opts[:exclude]
16
+ directory = opts[:directory]
17
+
18
+ command = Kanrisuru::Command.new('tar --restrict')
19
+
20
+ directory = realpath(directory, strip: true).path if directory
21
+ command.append_arg('-C', directory)
22
+ command.append_arg('-f', file)
23
+
24
+ set_compression(command, compress) if compress
25
+
26
+ case action
27
+ when 'list'
28
+ command.append_flag('-t')
29
+ command.append_arg('--occurrence', opts[:occurrence])
30
+ command.append_flag('--label', opts[:label])
31
+ command.append_flag('--multi-volume', opts[:multi_volume])
32
+
33
+ execute_shell(command)
34
+ Kanrisuru::Result.new(command) do |cmd|
35
+ items = cmd.to_a
36
+
37
+ items.map do |item|
38
+ FilePath.new(item)
39
+ end
40
+ end
41
+ when 'extract', 'get'
42
+ command.append_flag('-x')
43
+ command.append_arg('--occurrence', opts[:occurrence])
44
+ command.append_flag('--no-same-owner', opts[:no_same_owner])
45
+ command.append_flag('--no-same-permissions', opts[:no_same_permissions])
46
+ command.append_flag('--no-selinux', opts[:no_selinux])
47
+ command.append_flag('--no-xattrs', opts[:no_xattrs])
48
+ command.append_flag('--preserve-permissions', opts[:preserve_permissions])
49
+ command.append_flag('--same-owner', opts[:same_owners])
50
+ command.append_flag('--multi-volume', opts[:multi_volume])
51
+ command.append_flag('--label', opts[:label])
52
+ command.append_flag('--one-file-system ', opts[:one_file_system])
53
+ command.append_flag('--keep-old-files', opts[:keep_old_files])
54
+ command.append_flag('--skip-old-files', opts[:skip_old_files])
55
+ command.append_flag('--overwrite', opts[:overwrite])
56
+ command.append_flag('--overwrite-dir', opts[:overwrite_dir])
57
+ command.append_flag('--unlink-first', opts[:unlink_first])
58
+ command.append_flag('--recursive-unlink', opts[:recursive_unlink])
59
+
60
+ if Kanrisuru::Util.present?(paths)
61
+ paths = paths.instance_of(String) ? [paths] : paths
62
+ command << paths.join(' ')
63
+ end
64
+
65
+ execute_shell(command)
66
+ Kanrisuru::Result.new(command)
67
+ when 'create'
68
+ command.append_flag('-c')
69
+ command.append_flag('--multi-volume', opts[:multi_volume])
70
+
71
+ if Kanrisuru::Util.present?(exclude)
72
+ exclude = exclude.instance_of?(String) ? [exclude] : exclude
73
+ command.append_arg('--exclude', exclude.join(' '))
74
+ end
75
+
76
+ if Kanrisuru::Util.present?(paths)
77
+ paths = paths.instance_of?(String) ? [paths] : paths
78
+ command << paths.join(' ')
79
+ end
80
+
81
+ execute_shell(command)
82
+
83
+ Kanrisuru::Result.new(command)
84
+ when 'append'
85
+ command.append_flag('-r')
86
+
87
+ if Kanrisuru::Util.present?(paths)
88
+ paths = paths.instance_of?(String) ? [paths] : paths
89
+ command << paths.join(' ')
90
+ end
91
+
92
+ execute_shell(command)
93
+ Kanrisuru::Result.new(command)
94
+ when 'catenate', 'concat'
95
+ command.append_flag('-A')
96
+
97
+ if Kanrisuru::Util.present?(paths)
98
+ paths = paths.instance_of?(String) ? [paths] : paths
99
+ command << paths.join(' ')
100
+ end
101
+
102
+ execute_shell(command)
103
+ Kanrisuru::Result.new(command)
104
+ when 'update'
105
+ command.append_flag('-u')
106
+
107
+ if Kanrisuru::Util.present?(paths)
108
+ paths = paths.instance_of?(String) ? [paths] : paths
109
+ command << paths.join(' ')
110
+ end
111
+
112
+ execute_shell(command)
113
+ Kanrisuru::Result.new(command)
114
+ when 'diff', 'compare'
115
+ command.append_flag('-d')
116
+ command.append_arg('--occurrence', opts[:occurrence])
117
+
118
+ execute_shell(command)
119
+ Kanrisuru::Result.new(command)
120
+ when 'delete'
121
+ command.append_flag('--delete')
122
+ command.append_arg('--occurrence', opts[:occurrence])
123
+
124
+ if Kanrisuru::Util.present?(paths)
125
+ paths = paths.instance_of?(String) ? [paths] : paths
126
+ command << paths.join(' ')
127
+ end
128
+
129
+ execute_shell(command)
130
+ Kanrisuru::Result.new(command)
131
+ else
132
+ raise ArgumentError, 'Invalid argument action'
133
+ end
134
+ end
135
+
136
+ private
137
+
138
+ def set_compression(command, compress)
139
+ case compress
140
+ when 'bzip2'
141
+ command.append_flag('-j')
142
+ when 'xz'
143
+ command.append_flag('-J')
144
+ when 'gzip'
145
+ command.append_flag('-z')
146
+ when 'lzma'
147
+ command.append_flag('--lzma')
148
+ else
149
+ raise ArgumentError, "Invalid copmression program: #{compress}"
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,302 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Kanrisuru
6
+ module Core
7
+ module Disk
8
+ extend OsPackage::Define
9
+
10
+ os_define :linux, :df
11
+ os_define :linux, :du
12
+ os_define :linux, :blkid
13
+ os_define :linux, :lsblk
14
+
15
+ DiskUsage = Struct.new(:fsize, :path)
16
+ DiskFree = Struct.new(:file_system, :type, :total, :used, :capacity, :mount)
17
+ LsblkDevice = Struct.new(
18
+ :name, :maj_dev, :min_dev, :removable_device, :readonly_device, :owner, :group,
19
+ :mode, :fsize, :type, :mount_point, :fs_type, :uuid, :children
20
+ )
21
+
22
+ BlkidDevice = Struct.new(
23
+ :name, :label, :uuid, :type, :uuid_sub, :label_fatboot, :version, :usage,
24
+ :part_uuid, :part_entry_scheme, :part_entry_uuid, :part_entry_type,
25
+ :part_entry_number, :part_entry_offset, :part_entry_size, :part_entry_disk
26
+ )
27
+
28
+ def du(opts = {})
29
+ path = opts[:path]
30
+ convert = opts[:convert]
31
+
32
+ command = Kanrisuru::Command.new('du')
33
+ command.append_arg('-s', path)
34
+ command | "awk '{print $1, $2}'"
35
+
36
+ execute(command)
37
+
38
+ Kanrisuru::Result.new(command) do |cmd|
39
+ string = cmd.to_s
40
+ rows = string.split("\n")
41
+
42
+ rows.map do |row|
43
+ values = row.split
44
+ size = convert ? Kanrisuru::Util::Bits.convert_bytes(values[0], :byte, convert) : values[0]
45
+
46
+ DiskUsage.new(size, values[1])
47
+ end
48
+ end
49
+ end
50
+
51
+ def df(opts = {})
52
+ path = opts[:path]
53
+ inodes = opts[:inodes]
54
+
55
+ command = Kanrisuru::Command.new('df')
56
+
57
+ command.append_flag('-PT')
58
+ command.append_flag('-i', inodes)
59
+
60
+ command << path if Kanrisuru::Util.present?(path)
61
+ command | "awk '{print $1, $2, $3, $5, $6, $7}'"
62
+
63
+ execute(command)
64
+
65
+ Kanrisuru::Result.new(command) do |cmd|
66
+ items = []
67
+ rows = cmd.to_a
68
+ rows.each.with_index do |row, index|
69
+ next if index.zero?
70
+
71
+ values = row.split
72
+
73
+ items << DiskFree.new(
74
+ values[0],
75
+ values[1],
76
+ values[2].to_i,
77
+ values[3].to_i,
78
+ values[4].to_i,
79
+ values[5]
80
+ )
81
+ end
82
+ items
83
+ end
84
+ end
85
+
86
+ def blkid(opts = {})
87
+ label = opts[:label]
88
+ uuid = opts[:uuid]
89
+ device = opts[:device]
90
+
91
+ mode = ''
92
+ command = Kanrisuru::Command.new('blkid')
93
+
94
+ if Kanrisuru::Util.present?(label) || Kanrisuru::Util.present?(uuid)
95
+ mode = 'search'
96
+ command.append_arg('-L', opts[:label])
97
+ command.append_arg('-U', opts[:uuid])
98
+ elsif Kanrisuru::Util.present?(device)
99
+ mode = 'device'
100
+ command.append_arg('-po', 'export')
101
+ command << device
102
+ else
103
+ mode = 'list'
104
+ command.append_arg('-o', 'export')
105
+ end
106
+
107
+ execute_shell(command)
108
+
109
+ Kanrisuru::Result.new(command) do |cmd|
110
+ case mode
111
+ when 'search'
112
+ cmd.to_s
113
+ when 'device'
114
+ lines = cmd.to_a
115
+
116
+ ## Only gets 1 device
117
+ devices = blkid_devices(lines)
118
+ devices[0]
119
+ else
120
+ lines = cmd.to_a
121
+ blkid_devices(lines)
122
+ end
123
+ end
124
+ end
125
+
126
+ def lsblk(opts = {})
127
+ all = opts[:all]
128
+ nodeps = opts[:nodeps]
129
+ paths = opts[:paths]
130
+
131
+ command = Kanrisuru::Command.new('lsblk')
132
+
133
+ version = lsblk_version
134
+
135
+ ## lsblk after version 2.26 handles json parsing.
136
+ ## TODO: parse nested children for earlier version of lsblk
137
+ if version >= 2.27
138
+ command.append_flag('--json') if version >= 2.27
139
+ else
140
+ command.append_flag('-i')
141
+ command.append_flag('-P')
142
+ command.append_flag('--noheadings')
143
+ end
144
+
145
+ command.append_flag('-a', all)
146
+ command.append_flag('-p', paths)
147
+ command.append_flag('-p', nodeps)
148
+
149
+ command.append_arg('-o', 'NAME,FSTYPE,MAJ:MIN,MOUNTPOINT,SIZE,UUID,RO,RM,OWNER,GROUP,MODE,TYPE')
150
+ execute(command)
151
+
152
+ Kanrisuru::Result.new(command) do |cmd|
153
+ if version >= 2.27
154
+ result = cmd.to_json
155
+ devices = result['blockdevices']
156
+ build_lsblk_devices_json(devices)
157
+ else
158
+ build_lsblk_devices_text(cmd.to_a)
159
+ end
160
+ end
161
+ end
162
+
163
+ private
164
+
165
+ def blkid_devices(lines)
166
+ devices = []
167
+ current_device = nil
168
+
169
+ lines.each do |line|
170
+ value = line.split('=')[1]
171
+
172
+ if line =~ /^DEVNAME=/
173
+ current_device = BlkidDevice.new(value)
174
+ elsif line =~ /^UUID=/
175
+ current_device.uuid = value
176
+ elsif line =~ /^LABEL=/
177
+ current_device.label = value
178
+ elsif line =~ /^TYPE=/
179
+ current_device.type = value
180
+ elsif line =~ /^LABEL_FATBOOT=/
181
+ current_device.label_fatboot = value
182
+ elsif line =~ /^PARTUUID=/
183
+ current_device.part_uuid = value
184
+ elsif line =~ /^UUID_SUB=/
185
+ current_device.uuid_sub = value
186
+ elsif line =~ /^USAGE=/
187
+ current_device.usage = value
188
+ elsif line =~ /^VERSION=/
189
+ current_device.version = value.to_f
190
+ elsif line =~ /^PART_ENTRY_SCHEME=/
191
+ current_device.part_entry_scheme = value
192
+ elsif line =~ /^PART_ENTRY_UUID=/
193
+ current_device.part_entry_uuid = value
194
+ elsif line =~ /^PART_ENTRY_DISK=/
195
+ current_device.part_entry_disk = value
196
+ elsif line =~ /^PART_ENTRY_NUMBER=/
197
+ current_device.part_entry_number = value.to_i
198
+ elsif line =~ /^PART_ENTRY_OFFSET=/
199
+ current_device.part_entry_offset = value.to_i
200
+ elsif line =~ /^PART_ENTRY_SIZE=/
201
+ current_device.part_entry_size = value.to_i
202
+ elsif line =~ /^PART_ENTRY_TYPE=/
203
+ current_device.part_entry_type = value
204
+ elsif Kanrisuru::Util.blank?(line)
205
+ devices << current_device
206
+ current_device = nil
207
+ end
208
+ end
209
+
210
+ devices << current_device if Kanrisuru::Util.present?(current_device)
211
+ devices
212
+ end
213
+
214
+ def lsblk_version
215
+ command = Kanrisuru::Command.new('lsblk --version')
216
+ execute(command)
217
+
218
+ version = 0.00
219
+ regex = Regexp.new(/\d+(?:[,.]\d+)?/)
220
+
221
+ raise 'lsblk command not found' if command.failure?
222
+
223
+ version = command.to_s.scan(regex)[0].to_f unless regex.match(command.to_s).nil?
224
+
225
+ version
226
+ end
227
+
228
+ def build_lsblk_devices_text(lines)
229
+ devices = []
230
+
231
+ lines.each do |line|
232
+ values = line.split
233
+
234
+ current_device = LsblkDevice.new
235
+
236
+ values.each do |value|
237
+ key, value = value.split('=')
238
+ value = value.gsub(/"/, '')
239
+
240
+ case key
241
+ when 'NAME'
242
+ current_device.name = value
243
+ when 'FSTYPE'
244
+ current_device.fs_type = value
245
+ when 'MAJ:MIN'
246
+ maj, min = value.split(':')
247
+ current_device.maj_dev = maj
248
+ current_device.min_dev = min
249
+ when 'MOUNTPOINT'
250
+ current_device.mount_point = value
251
+ when 'SIZE'
252
+ current_device.fsize = value
253
+ when 'UUID'
254
+ current_device.uuid = value
255
+ when 'RO'
256
+ current_device.readonly_device = value
257
+ when 'RM'
258
+ current_device.removable_device = value
259
+ when 'OWNER'
260
+ current_device.owner = value
261
+ when 'GROUP'
262
+ current_device.group = value
263
+ when 'MODE'
264
+ current_device.mode = value
265
+ when 'TYPE'
266
+ current_device.type = value
267
+ end
268
+ end
269
+
270
+ devices << current_device
271
+ end
272
+
273
+ devices
274
+ end
275
+
276
+ def build_lsblk_devices_json(devices)
277
+ devices.map do |device|
278
+ children = (build_lsblk_devices_json(device['children']) if device.key?('children'))
279
+
280
+ maj_min = device['maj:min']
281
+
282
+ LsblkDevice.new(
283
+ device['name'],
284
+ maj_min ? maj_min.split(':')[0] : nil,
285
+ maj_min ? maj_min.split(':')[1] : nil,
286
+ device['rm'],
287
+ device['ro'],
288
+ device['owner'],
289
+ device['group'],
290
+ device['mode'],
291
+ device['size'],
292
+ device['type'],
293
+ device['mountpoint'],
294
+ device['fstype'],
295
+ device['uuid'],
296
+ children
297
+ )
298
+ end
299
+ end
300
+ end
301
+ end
302
+ end