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,332 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module Kanrisuru
6
+ module Core
7
+ module File
8
+ extend OsPackage::Define
9
+
10
+ os_define :linux, :touch
11
+ os_define :linux, :cp
12
+ os_define :linux, :copy
13
+ os_define :linux, :mkdir
14
+ os_define :linux, :mv
15
+ os_define :linux, :move
16
+
17
+ os_define :linux, :link
18
+ os_define :linux, :symlink
19
+ os_define :linux, :ln
20
+ os_define :linux, :ln_s
21
+
22
+ os_define :linux, :chmod
23
+ os_define :linux, :chown
24
+
25
+ os_define :linux, :unlink
26
+ os_define :linux, :rm
27
+ os_define :linux, :rmdir
28
+
29
+ os_define :linux, :wc
30
+
31
+ FileCount = Struct.new(:lines, :words, :characters)
32
+
33
+ def cp(source, dest, opts = {})
34
+ backup = opts[:backup]
35
+ command = Kanrisuru::Command.new('cp')
36
+
37
+ command.append_flag('-R', opts[:recursive])
38
+ command.append_flag('-x', opts[:one_file_system])
39
+ command.append_flag('-u', opts[:update])
40
+ command.append_flag('-L', opts[:follow])
41
+ command.append_flag('-n', opts[:no_clobber])
42
+ command.append_flag('--strip-trailing-slashes', opts[:strip_trailing_slashes])
43
+
44
+ if backup.instance_of?(TrueClass)
45
+ command.append_flag('-b')
46
+ elsif Kanrisuru::Util.present?(backup)
47
+ raise ArgumentError, 'invalid backup control value' unless backup_control_valid?(backup)
48
+
49
+ command << "--backup=#{backup}"
50
+ end
51
+
52
+ if opts[:preserve].instance_of?(TrueClass)
53
+ command.append_flag('-p')
54
+ elsif Kanrisuru::Util.present?(opts[:preserve])
55
+ preserve =
56
+ (opts[:preserve].join(',') if opts[:preserve].instance_of?(Array))
57
+
58
+ command << "--preserve=#{preserve}"
59
+ end
60
+
61
+ if opts[:no_target_directory]
62
+ command.append_flag('-T')
63
+ command << source
64
+ command << dest
65
+ elsif opts[:target_directory]
66
+ command.append_arg('-t', dest)
67
+
68
+ source = source.instance_of?(String) ? [source] : source
69
+ command << source.join(' ')
70
+ else
71
+ source = source.instance_of?(String) ? [source] : source
72
+ command << source.join(' ')
73
+ command << dest
74
+ end
75
+
76
+ execute_shell(command)
77
+
78
+ Kanrisuru::Result.new(command)
79
+ end
80
+
81
+ def copy(source, dest, opts = {})
82
+ cp(source, dest, opts)
83
+ end
84
+
85
+ def mv(source, dest, opts = {})
86
+ backup = opts[:backup]
87
+ command = Kanrisuru::Command.new('mv')
88
+
89
+ command.append_flag('--strip-trailing-slashes', opts[:strip_trailing_slashes])
90
+
91
+ if opts[:force]
92
+ command.append_flag('-f')
93
+ elsif opts[:no_clobber]
94
+ command.append_flag('-n')
95
+ end
96
+
97
+ if backup.instance_of?(TrueClass)
98
+ command.append_flag('-b')
99
+ elsif Kanrisuru::Util.present?(backup)
100
+ raise ArgumentError, 'invalid backup control value' unless backup_control_valid?(backup)
101
+
102
+ command << "--backup=#{backup}"
103
+ end
104
+
105
+ if opts[:no_target_directory]
106
+ command.append_flag('-T')
107
+ command << source
108
+ command << dest
109
+ elsif opts[:target_directory]
110
+ command.append_arg('-t', dest)
111
+
112
+ source = source.instance_of?(String) ? [source] : source
113
+ command << source.join(' ')
114
+ else
115
+ source = source.instance_of?(String) ? [source] : source
116
+
117
+ command << source.join(' ')
118
+ command << dest
119
+ end
120
+
121
+ execute_shell(command)
122
+
123
+ Kanrisuru::Result.new(command)
124
+ end
125
+
126
+ def move(source, dest, opts = {})
127
+ mv(source, dest, opts)
128
+ end
129
+
130
+ def link(src, dest, opts = {})
131
+ ln(src, dest, opts)
132
+ end
133
+
134
+ def symlink(src, dest, opts = {})
135
+ ln_s(src, dest, opts)
136
+ end
137
+
138
+ def ln(src, dest, opts = {})
139
+ ## Can't hardlink dirs
140
+ return false if dir?(src)
141
+
142
+ command = Kanrisuru::Command.new("ln #{src} #{dest}")
143
+ command.append_flag('-f', opts[:force])
144
+
145
+ execute_shell(command)
146
+
147
+ Kanrisuru::Result.new(command) do
148
+ stat(dest).data
149
+ end
150
+ end
151
+
152
+ def ln_s(src, dest, opts = {})
153
+ return if src == dest
154
+
155
+ ## Use absolute path for source
156
+ real_src = realpath(src).path
157
+
158
+ ## Not valid if no real path, not an existing inode, or root
159
+ raise ArgumentError, 'Invalid path' if Kanrisuru::Util.blank?(real_src) || !inode?(real_src) || real_src == '/'
160
+
161
+ dest_is_dir = dir?(dest)
162
+
163
+ ## Don't symlink inside an already existing symlink
164
+ return if symlink?(dest) && dest_is_dir
165
+
166
+ real_dest =
167
+ if dest_is_dir
168
+ ## Use real path for destination
169
+ realpath(dest).path
170
+ else
171
+ ## Use standard path
172
+ dest
173
+ end
174
+
175
+ return unless real_dest
176
+
177
+ command = Kanrisuru::Command.new("ln -s #{real_src} #{real_dest}")
178
+ command.append_flag('-f', opts[:force])
179
+
180
+ execute_shell(command)
181
+
182
+ Kanrisuru::Result.new(command) do
183
+ stat(real_dest).data
184
+ end
185
+ end
186
+
187
+ def unlink(path)
188
+ command = Kanrisuru::Command.new("unlink #{path}")
189
+ execute_shell(command)
190
+ Kanrisuru::Result.new(command)
191
+ end
192
+
193
+ def rm(paths, opts = {})
194
+ paths = [paths] if paths.instance_of?(String)
195
+
196
+ paths.each do |path|
197
+ raise ArgumentError, "Can't delete root path" if path == '/' || realpath(path).path == '/'
198
+ end
199
+
200
+ command = Kanrisuru::Command.new("rm #{paths.join(' ')} --preserve-root")
201
+ command.append_flag('-f', opts[:force])
202
+ command.append_flag('-r', opts[:recursive])
203
+
204
+ execute_shell(command)
205
+
206
+ Kanrisuru::Result.new(command)
207
+ end
208
+
209
+ def rmdir(path)
210
+ return false unless dir?(path)
211
+
212
+ rm(path, force: true, recursive: true)
213
+ end
214
+
215
+ def mkdir(path, opts = {})
216
+ owner = opts[:owner]
217
+ group = opts[:group]
218
+ recursive = opts[:recursive]
219
+
220
+ command = Kanrisuru::Command.new("mkdir #{path}")
221
+ command.append_flag('-p', opts[:silent])
222
+ command.append_arg('-m', opts[:mode])
223
+
224
+ execute_shell(command)
225
+
226
+ Kanrisuru::Result.new(command) do
227
+ if Kanrisuru::Util.present?(owner) || Kanrisuru::Util.present?(group)
228
+ chown(path, owner: owner, group: group, recursive: recursive)
229
+ end
230
+
231
+ stat(path).data
232
+ end
233
+ end
234
+
235
+ def touch(paths, opts = {})
236
+ date = opts[:date]
237
+
238
+ paths = [paths] if paths.instance_of?(String)
239
+ command = Kanrisuru::Command.new("touch #{paths.join(' ')}")
240
+
241
+ command.append_flag('-a', opts[:atime])
242
+ command.append_flag('-m', opts[:mtime])
243
+ command.append_flag('-c', opts[:nofiles])
244
+
245
+ if Kanrisuru::Util.present?(date)
246
+ date = Date.parse(date) if date.instance_of?(String)
247
+ command.append_arg('-d', date)
248
+ end
249
+
250
+ command.append_arg('-r', opts[:reference])
251
+
252
+ execute_shell(command)
253
+
254
+ Kanrisuru::Result.new(command) do
255
+ paths.map do |path|
256
+ stat(path).data
257
+ end
258
+ end
259
+ end
260
+
261
+ def chmod(path, mode, opts = {})
262
+ recursive = opts[:recursive]
263
+
264
+ command =
265
+ if mode.instance_of?(String) && (mode.include?(',') || /[=+-]/.match(mode))
266
+ Kanrisuru::Command.new("chmod #{mode} #{path}")
267
+ elsif mode.instance_of?(Kanrisuru::Mode)
268
+ Kanrisuru::Command.new("chmod #{mode.numeric} #{path}")
269
+ else
270
+ mode = Kanrisuru::Mode.new(mode)
271
+ Kanrisuru::Command.new("chmod #{mode.numeric} #{path}")
272
+ end
273
+
274
+ command.append_flag('-R', recursive)
275
+
276
+ execute_shell(command)
277
+
278
+ Kanrisuru::Result.new(command) do
279
+ stat(path).data
280
+ end
281
+ end
282
+
283
+ def chown(path, opts = {})
284
+ owner = opts[:owner]
285
+ group = opts[:group]
286
+
287
+ uid = get_uid(owner).to_i if Kanrisuru::Util.present?(owner)
288
+ gid = get_gid(group).to_i if Kanrisuru::Util.present?(group)
289
+
290
+ ## Don't chown a blank owner and group.
291
+ return false if Kanrisuru::Util.blank?(uid) && Kanrisuru::Util.blank?(gid)
292
+
293
+ command = Kanrisuru::Command.new('chown')
294
+
295
+ arg = ''
296
+ arg = uid.to_s if Kanrisuru::Util.present?(uid)
297
+ arg += ":#{gid}" if Kanrisuru::Util.present?(gid)
298
+
299
+ command.append_value(arg)
300
+ command.append_flag('-R', opts[:recursive])
301
+
302
+ command << path
303
+
304
+ execute_shell(command)
305
+
306
+ Kanrisuru::Result.new(command) do
307
+ stat(path).data
308
+ end
309
+ end
310
+
311
+ def wc(file)
312
+ command = Kanrisuru::Command.new("wc #{file}")
313
+ execute_shell(command)
314
+
315
+ Kanrisuru::Result.new(command) do |cmd|
316
+ items = cmd.to_a
317
+ FileCount.new(items[0].to_i, items[1].to_i, items[2].to_i)
318
+ end
319
+ end
320
+
321
+ private
322
+
323
+ def backup_control_valid?(backup)
324
+ opts = %w[
325
+ none off numbered t existing nil simple never
326
+ ]
327
+
328
+ opts.include?(backup)
329
+ end
330
+ end
331
+ end
332
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module Kanrisuru
6
+ module Core
7
+ module Find
8
+ extend OsPackage::Define
9
+
10
+ os_define :linux, :find
11
+
12
+ FilePath = Struct.new(:path)
13
+
14
+ def find(opts = {})
15
+ paths = opts[:paths]
16
+ type = opts[:type]
17
+ regex = opts[:regex]
18
+ size = opts[:size]
19
+
20
+ command = Kanrisuru::Command.new('find')
21
+
22
+ case opts[:follow]
23
+ when 'never'
24
+ command.append_flag('-P')
25
+ when 'always'
26
+ command.append_flag('-L')
27
+ when 'command'
28
+ command.append_flag('-H')
29
+ end
30
+
31
+ if Kanrisuru::Util.present?(paths)
32
+ if paths.instance_of?(Array)
33
+ paths = paths.join(' ')
34
+ elsif paths.class != String
35
+ raise 'Invalid paths type'
36
+ end
37
+
38
+ command << paths
39
+ end
40
+
41
+ command.append_flag('-executable', opts[:executable])
42
+ command.append_flag('-empty', opts[:empty])
43
+ command.append_flag('-readable', opts[:readable])
44
+ command.append_flag('-writable', opts[:writable])
45
+ command.append_flag('-nogroup', opts[:nogroup])
46
+ command.append_flag('-nouser', opts[:nouser])
47
+ command.append_flag('-mount', opts[:mount])
48
+
49
+ command.append_arg('-path', opts[:path])
50
+ command.append_arg('-name', opts[:name])
51
+ command.append_arg('-gid', opts[:gid])
52
+ command.append_arg('-uid', opts[:uid])
53
+ command.append_arg('-user', opts[:user])
54
+ command.append_arg('-group', opts[:group])
55
+ command.append_arg('-inum', opts[:inode])
56
+ command.append_arg('-links', opts[:links])
57
+ command.append_arg('-maxdepth', opts[:maxdepth])
58
+ command.append_arg('-mindepth', opts[:mindepth])
59
+
60
+ command.append_arg('-atime', opts[:atime])
61
+ command.append_arg('-ctime', opts[:ctime])
62
+ command.append_arg('-mtime', opts[:mtime])
63
+ command.append_arg('-amin', opts[:amin])
64
+ command.append_arg('-cmin', opts[:cmin])
65
+ command.append_arg('-mmin', opts[:mmin])
66
+
67
+ command.append_arg('-regex', "'#{regex}'") if Kanrisuru::Util.present?(regex)
68
+
69
+ if size.instance_of?(String)
70
+ match = Regexp.new(/^([-+]+)\s*?(\d+)([bcwkMG])$/).match(size)
71
+
72
+ raise ArgumentError, "invalid size string: '#{@size}'" if match.nil? || match.captures.include?(nil)
73
+
74
+ command.append_arg('-size', size)
75
+ elsif size.instance_of?(Integer)
76
+ command.append_arg('-size', size)
77
+ end
78
+
79
+ case type
80
+ when 'directory'
81
+ command.append_arg('-type', 'd')
82
+ when 'file'
83
+ command.append_arg('-type', 'f')
84
+ when 'symlinks'
85
+ command.append_arg('-type', 'l')
86
+ when 'block'
87
+ command.append_arg('-type', 'b')
88
+ when 'character'
89
+ command.append_arg('-type', 'c')
90
+ when 'pipe'
91
+ command.append_arg('-type', 'p')
92
+ when 'socket'
93
+ command.append_arg('-type', 's')
94
+ end
95
+
96
+ execute_shell(command)
97
+
98
+ Kanrisuru::Result.new(command) do |cmd|
99
+ rows = cmd.to_a
100
+
101
+ rows.map do |row|
102
+ FilePath.new(row)
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ module Core
5
+ module Group
6
+ extend OsPackage::Define
7
+
8
+ os_define :linux, :group?
9
+ os_define :linux, :get_gid
10
+ os_define :linux, :get_group
11
+ os_define :linux, :create_group
12
+ os_define :linux, :update_group
13
+ os_define :linux, :delete_group
14
+
15
+ Group = Struct.new(:gid, :name, :users)
16
+ GroupUser = Struct.new(:uid, :name)
17
+
18
+ def group?(group)
19
+ result = get_gid(group)
20
+ return false if result.failure?
21
+
22
+ Kanrisuru::Util.present?(result.data) && result.data.instance_of?(Integer)
23
+ end
24
+
25
+ def get_gid(group)
26
+ command = Kanrisuru::Command.new("getent group #{group}")
27
+
28
+ execute(command)
29
+
30
+ Kanrisuru::Result.new(command) do |cmd|
31
+ cmd.to_s.split(':')[2].to_i
32
+ end
33
+ end
34
+
35
+ def get_group(group)
36
+ command = Kanrisuru::Command.new("getent group #{group} | cut -d: -f4")
37
+
38
+ execute(command)
39
+
40
+ Kanrisuru::Result.new(command) do |cmd|
41
+ ## Get group id
42
+ result = get_gid(group)
43
+ break if result.failure?
44
+
45
+ gid = result.to_i
46
+
47
+ array = cmd.to_s.split(',')
48
+ users = array.map do |user|
49
+ uid = get_uid(user)
50
+ GroupUser.new(uid.to_i, user)
51
+ end
52
+
53
+ Group.new(gid, group, users)
54
+ end
55
+ end
56
+
57
+ def create_group(group, opts = {})
58
+ gid = opts[:gid]
59
+
60
+ command = Kanrisuru::Command.new("groupadd #{group}")
61
+ command.append_arg('-g', gid)
62
+
63
+ execute_shell(command)
64
+
65
+ Kanrisuru::Result.new(command) do
66
+ gid = Kanrisuru::Util.present?(gid) ? gid : get_gid(group).data
67
+ Group.new(gid, group)
68
+ end
69
+ end
70
+
71
+ def update_group(group, opts = {})
72
+ gid = opts[:gid]
73
+ return if Kanrisuru::Util.blank?(gid) || Kanrisuru::Util.blank?(opts[:new_name])
74
+
75
+ command = Kanrisuru::Command.new("groupmod #{group}")
76
+ command.append_arg('-g', gid)
77
+ command.append_arg('-n', opts[:new_name])
78
+
79
+ execute_shell(command)
80
+
81
+ Kanrisuru::Result.new(command) do
82
+ gid = Kanrisuru::Util.present?(gid) ? gid : get_gid(group).data
83
+ Group.new(gid, group)
84
+ end
85
+ end
86
+
87
+ def delete_group(group)
88
+ return false unless group?(group)
89
+
90
+ command = Kanrisuru::Command.new("groupdel #{group}")
91
+ execute_shell(command)
92
+
93
+ Kanrisuru::Result.new(command)
94
+ end
95
+ end
96
+ end
97
+ end