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,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kanrisuru
4
+ module Core
5
+ module Mount
6
+ extend OsPackage::Define
7
+
8
+ os_define :linux, :mount
9
+ os_define :linux, :umount
10
+
11
+ def mount(opts = {})
12
+ type = opts[:type]
13
+ all = opts[:all]
14
+ device = opts[:device]
15
+ directory = opts[:directory]
16
+
17
+ bind_old = opts[:bind_old]
18
+ bind_new = opts[:bind_new]
19
+ rbind_old = opts[:rbind_old]
20
+ rbind_new = opts[:rbind_new]
21
+ move_old = opts[:move_old]
22
+ move_new = opts[:move_new]
23
+ fs_opts = opts[:fs_opts]
24
+
25
+ command = Kanrisuru::Command.new('mount')
26
+
27
+ if Kanrisuru::Util.present?(bind_old) && Kanrisuru::Util.present?(bind_new)
28
+ command.append_flag('--bind')
29
+ command << bind_old
30
+ command << bind_new
31
+ elsif Kanrisuru::Util.present?(rbind_old) && Kanrisuru::Util.present?(rbind_new)
32
+ command.append_flag('--rbind')
33
+ command << rbind_old
34
+ command << rbind_new
35
+ elsif Kanrisuru::Util.present?(move_old) && Kanrisuru::Util.present?(move_new)
36
+ command.append_flag('--move')
37
+ command << move_old
38
+ command << move_new
39
+ else
40
+ command.append_arg('-L', opts[:label])
41
+ command.append_arg('-U', opts[:uuid])
42
+ command.append_flag('-n', opts[:no_mtab])
43
+ command.append_flag('-f', opts[:fake])
44
+ command.append_flag('-i', opts[:internal_only])
45
+ command.append_flag('-s', opts[:sloppy])
46
+
47
+ command.append_flag('--no-mtab', opts[:no_mtab])
48
+ command.append_flag('--no-canonicalizeb', opts[:no_canonicalize])
49
+
50
+ fs_options = nil
51
+ if Kanrisuru::Util.present?(type)
52
+ add_type(command, type)
53
+ fs_options = Kanrisuru::Remote::Fstab::Options.new(type, fs_opts) if fs_opts
54
+ elsif fs_opts
55
+ fs_options = Kanrisuru::Remote::Fstab::Options.new('common', fs_opts)
56
+ end
57
+
58
+ if Kanrisuru::Util.present?(all)
59
+ command.append_flag('-a')
60
+ add_test_opts(command, opts[:test_opts], type)
61
+ else
62
+ command.append_arg('-o', fs_options.to_s)
63
+
64
+ command << device if Kanrisuru::Util.present?(device)
65
+ command << directory if Kanrisuru::Util.present?(directory)
66
+ end
67
+ end
68
+
69
+ execute_shell(command)
70
+ Kanrisuru::Result.new(command)
71
+ end
72
+
73
+ def umount(opts = {})
74
+ all = opts[:all]
75
+ type = opts[:type]
76
+ command = Kanrisuru::Command.new('umount')
77
+
78
+ if Kanrisuru::Util.present?(all)
79
+ command.append_flag('-a')
80
+ add_type(command, type)
81
+ add_test_opts(command, opts[:test_opts], type)
82
+ end
83
+
84
+ command.append_flag('--fake', opts[:fake])
85
+ command.append_flag('--no-canonicalize', opts[:no_canonicalize])
86
+ command.append_flag('-n', opts[:no_mtab])
87
+ command.append_flag('-r', opts[:fail_remount_readonly])
88
+ command.append_flag('-d', opts[:free_loopback])
89
+
90
+ command.append_flag('-l', opts[:lazy])
91
+ command.append_flag('-f', opts[:force])
92
+
93
+ execute_shell(command)
94
+
95
+ Kanrisuru::Result.new(command)
96
+ end
97
+
98
+ private
99
+
100
+ def add_type(command, type)
101
+ return unless Kanrisuru::Util.present?(type)
102
+
103
+ test_types = nil
104
+
105
+ if type.include?(',')
106
+ if type.include?('no')
107
+ test_types = type.gsub('no', '')
108
+ test_types = test_types.split(',')
109
+ else
110
+ test_types = type.split(',')
111
+ end
112
+ else
113
+ test_types = [type]
114
+ end
115
+
116
+ test_types.each do |t|
117
+ device_opts = Kanrisuru::Util::FsMountOpts.get_device(t)
118
+ raise ArugmentError, "Invalid fstype: #{t}" unless device_opts
119
+ end
120
+
121
+ command.append_arg('-t', type)
122
+ end
123
+
124
+ def add_test_opts(command, test_opts, type)
125
+ return unless Kanrisuru::Util.present?(test_opts)
126
+
127
+ test_options =
128
+ if Kanrisuru::Util.present?(type)
129
+ Kanrisuru::Remote::Fstab::Options.new(type, test_opts)
130
+ else
131
+ Kanrisuru::Remote::Fstab::Options.new('common', test_opts)
132
+ end
133
+
134
+ command.append_arg('-O', test_options.to_s)
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module Kanrisuru
6
+ module Core
7
+ module Path
8
+ extend OsPackage::Define
9
+
10
+ os_define :linux, :ls
11
+ os_define :linux, :pwd
12
+ os_define :linux, :whoami
13
+ os_define :linux, :which
14
+ os_define :linux, :realpath
15
+ os_define :linux, :readlink
16
+
17
+ FilePath = Struct.new(:path)
18
+ FileInfoId = Struct.new(:inode, :mode, :memory_blocks, :uid, :gid, :fsize, :date, :path, :type)
19
+ FileInfo = Struct.new(:inode, :mode, :memory_blocks, :owner, :group, :fsize, :date, :path, :type)
20
+ UserName = Struct.new(:user)
21
+
22
+ def ls(opts = {})
23
+ path = opts[:path]
24
+ all = opts[:all]
25
+ id = opts[:id]
26
+
27
+ command = Kanrisuru::Command.new('ls')
28
+ command.append_flag('-i')
29
+ command.append_flag('-l')
30
+ command.append_flag('-a', all)
31
+ command.append_flag('-n', id)
32
+
33
+ command << (path || pwd.path)
34
+ execute_shell(command)
35
+
36
+ Kanrisuru::Result.new(command) do |cmd|
37
+ items = []
38
+ rows = cmd.to_a
39
+
40
+ rows.each.with_index do |row, index|
41
+ next if index.zero?
42
+
43
+ values = row.split
44
+ date = DateTime.parse("#{values[6]} #{values[7]} #{values[8]}")
45
+
46
+ type = values[1].include?('d') ? 'directory' : 'file'
47
+
48
+ items <<
49
+ if id
50
+ FileInfoId.new(
51
+ values[0].to_i,
52
+ Kanrisuru::Mode.new(values[1]),
53
+ values[2].to_i,
54
+ values[3].to_i,
55
+ values[4].to_i,
56
+ values[5].to_i,
57
+ date,
58
+ values[9],
59
+ type
60
+ )
61
+ else
62
+ FileInfo.new(
63
+ values[0].to_i,
64
+ Kanrisuru::Mode.new(values[1]),
65
+ values[2].to_i,
66
+ values[3],
67
+ values[4],
68
+ values[5].to_i,
69
+ date,
70
+ values[9],
71
+ type
72
+ )
73
+ end
74
+ end
75
+
76
+ items
77
+ end
78
+ end
79
+
80
+ def whoami
81
+ command = Kanrisuru::Command.new('whoami')
82
+ execute_shell(command)
83
+
84
+ Kanrisuru::Result.new(command) do |cmd|
85
+ UserName.new(cmd.to_s)
86
+ end
87
+ end
88
+
89
+ def pwd
90
+ command = Kanrisuru::Command.new('pwd')
91
+ execute_shell(command)
92
+
93
+ Kanrisuru::Result.new(command) do |cmd|
94
+ FilePath.new(cmd.to_s)
95
+ end
96
+ end
97
+
98
+ def which(program, opts = {})
99
+ command = Kanrisuru::Command.new('which')
100
+ command.append_flag('-a', opts[:all])
101
+ command << program
102
+
103
+ execute_shell(command)
104
+
105
+ Kanrisuru::Result.new(command) do |cmd|
106
+ rows = cmd.to_a
107
+ rows.map do |row|
108
+ FilePath.new(row)
109
+ end
110
+ end
111
+ end
112
+
113
+ def realpath(path, opts = {})
114
+ command = Kanrisuru::Command.new("realpath #{path}")
115
+ command.append_flag('-s', opts[:strip])
116
+
117
+ execute(command)
118
+
119
+ Kanrisuru::Result.new(command) do |cmd|
120
+ FilePath.new(cmd.to_s)
121
+ end
122
+ end
123
+
124
+ def readlink(path, opts = {})
125
+ command = Kanrisuru::Command.new('readlink')
126
+ command.append_flag('-f', opts[:canonicalize])
127
+ command.append_flag('-e', opts[:canonicalize_existing])
128
+ command.append_flag('-m', opts[:canonicalize_missing])
129
+
130
+ command << path
131
+
132
+ execute(command)
133
+
134
+ Kanrisuru::Result.new(command) do |cmd|
135
+ FilePath.new(cmd.to_s)
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ipaddr'
4
+
5
+ module Kanrisuru
6
+ module Core
7
+ module Socket
8
+ extend OsPackage::Define
9
+
10
+ os_define :linux, :ss
11
+
12
+ SocketStatistics = Struct.new(
13
+ :netid, :state, :receive_queue, :send_queue,
14
+ :local_address, :local_port, :peer_address, :peer_port,
15
+ :memory
16
+ )
17
+
18
+ SocketStatisticsMemory = Struct.new(
19
+ :rmem_alloc, :rcv_buf, :wmem_alloc, :snd_buf,
20
+ :fwd_alloc, :wmem_queued, :ropt_mem, :back_log, :sock_drop
21
+ )
22
+
23
+ TCP_STATES = %w[
24
+ established syn-sent syn-recv
25
+ fin-wait-1 fin-wait-2 time-wait
26
+ closed close-wait last-ack listening closing
27
+ ].freeze
28
+
29
+ OTHER_STATES = %w[
30
+ all connected synchronized bucket syn-recv
31
+ big
32
+ ].freeze
33
+
34
+ TCP_STATE_ABBR = {
35
+ 'ESTAB' => 'established', 'LISTEN' => 'listening', 'UNCONN' => 'unconnected',
36
+ 'SYN-SENT' => 'syn-sent', 'SYN-RECV' => 'syn-recv', 'FIN-WAIT-1' => 'fin-wait-1',
37
+ 'FIN-WAIT-2' => 'fin-wait-2', 'TIME-WAIT' => 'time-wait', 'CLOSE-WAIT' => 'close-wait',
38
+ 'LAST-ACK' => 'last-ack', 'CLOSING' => 'closing'
39
+ }.freeze
40
+
41
+ def ss(opts = {})
42
+ state = opts[:state]
43
+ expression = opts[:expression]
44
+
45
+ command = Kanrisuru::Command.new('ss')
46
+
47
+ command.append_flag('-a')
48
+ command.append_flag('-m')
49
+
50
+ command.append_flag('-n', opts[:numeric])
51
+ command.append_flag('-t', opts[:tcp])
52
+ command.append_flag('-u', opts[:udp])
53
+ command.append_flag('-x', opts[:unix])
54
+ command.append_flag('-w', opts[:raw])
55
+
56
+ command.append_arg('-f', opts[:family])
57
+
58
+ if Kanrisuru::Util.present?(state)
59
+ raise ArgumentError, 'invalid filter state' if !TCP_STATES.include?(state) && !OTHER_STATES.include?(state)
60
+
61
+ command.append_arg('state', state)
62
+ end
63
+
64
+ command << expression if Kanrisuru::Util.present?(expression)
65
+
66
+ execute_shell(command)
67
+
68
+ Kanrisuru::Result.new(command) do |cmd|
69
+ rows = []
70
+
71
+ ## New lines with tabs are from text overflow
72
+ ## on on stdout of SS command.
73
+ ## Replace the newline and tab chars with a space.
74
+ string = cmd.raw_result.join
75
+ string = string.gsub("\n\t", "\s")
76
+ lines = string.lines.map(&:strip)
77
+
78
+ headers = lines.shift
79
+
80
+ lines.each do |line|
81
+ values = line.split
82
+ next if values.length < 5
83
+
84
+ socket_stats = SocketStatistics.new
85
+
86
+ socket_stats.netid = if headers.include?('Netid')
87
+ values.shift
88
+ elsif opts[:tcp]
89
+ 'tcp'
90
+ elsif opts[:udp]
91
+ 'udp'
92
+ elsif opts[:raw]
93
+ 'raw'
94
+ else
95
+ ''
96
+ end
97
+
98
+ socket_stats.state = if headers.include?('State')
99
+ TCP_STATE_ABBR[values.shift]
100
+ else
101
+ state
102
+ end
103
+
104
+ socket_stats.receive_queue = values.shift.to_i
105
+ socket_stats.send_queue = values.shift.to_i
106
+
107
+ address, port = parse_address_port(values)
108
+ socket_stats.local_address = address
109
+ socket_stats.local_port = port
110
+
111
+ address, port = parse_address_port(values)
112
+ socket_stats.peer_address = address
113
+ socket_stats.peer_port = port
114
+
115
+ socket_stats.memory = parse_memory(values.shift)
116
+
117
+ rows << socket_stats
118
+ end
119
+
120
+ rows
121
+ end
122
+ end
123
+
124
+ private
125
+
126
+ def parse_memory(string)
127
+ return if Kanrisuru::Util.blank?(string) ||
128
+ Regexp.new(/skmem:\((\S+)\)/).match(string).nil?
129
+
130
+ _, string = string.split(/skmem:\((\S+)\)/)
131
+ values = string.split(',')
132
+
133
+ memory = SocketStatisticsMemory.new
134
+ memory.rmem_alloc = values[0].split(/(\d+)/)[1].to_i
135
+ memory.rcv_buf = values[1].split(/(\d+)/)[1].to_i
136
+ memory.wmem_alloc = values[2].split(/(\d+)/)[1].to_i
137
+ memory.snd_buf = values[3].split(/(\d+)/)[1].to_i
138
+ memory.fwd_alloc = values[4].split(/(\d+)/)[1].to_i
139
+ memory.wmem_queued = values[5].split(/(\d+)/)[1].to_i
140
+ memory.ropt_mem = values[6].split(/(\d+)/)[1].to_i
141
+ memory.back_log = values[7].split(/(\d+)/)[1].to_i
142
+ memory.sock_drop = values[8].split(/(\d+)/)[1].to_i
143
+
144
+ memory
145
+ end
146
+
147
+ def parse_address_port(values)
148
+ address = values.shift
149
+ port = nil
150
+
151
+ if address == '*' && Regexp.new(/skmem:\((\S+)\)/).match(values[0])
152
+ port = '*'
153
+ elsif Regexp.new(/\[(\S+)\]/).match(address)
154
+ tokens = address.split(/\[(\S+)\]/)
155
+ address = "[#{tokens[1]}]"
156
+ _, port = tokens[2].split(/:(\S+)/)
157
+ elsif Regexp.new(/:\S+/).match(address)
158
+ address, port = address.split(/:(\S+)/)
159
+ else
160
+ port = values.shift
161
+ end
162
+
163
+ port = Kanrisuru::Util.numeric?(port) ? port.to_i : port
164
+ [address, port]
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module Kanrisuru
6
+ module Core
7
+ module Stat
8
+ extend OsPackage::Define
9
+
10
+ os_define :linux, :dir?
11
+ os_define :linux, :file?
12
+ os_define :linux, :block_device?
13
+ os_define :linux, :char_device?
14
+ os_define :linux, :symlink?
15
+ os_define :linux, :file_type?
16
+ os_define :linux, :inode?
17
+ os_define :linux, :stat
18
+
19
+ FileStat = Struct.new(
20
+ :mode, :blocks, :device, :file_type,
21
+ :gid, :group, :links, :inode,
22
+ :path, :fsize, :uid, :user,
23
+ :last_access, :last_modified, :last_changed
24
+ )
25
+
26
+ def dir?(path)
27
+ file_type?(path, 'directory')
28
+ end
29
+
30
+ def file?(path)
31
+ file_type?(path, 'regular file')
32
+ end
33
+
34
+ def empty_file?(path)
35
+ file_type?(path, 'regular empty file')
36
+ end
37
+
38
+ def block_device?(path)
39
+ file_type?(path, 'block special file')
40
+ end
41
+
42
+ def char_device?(path)
43
+ file_type?(path, 'character special file')
44
+ end
45
+
46
+ def symlink?(path)
47
+ file_type?(path, 'symbolic link')
48
+ end
49
+
50
+ def inode?(path)
51
+ command = Kanrisuru::Command.new("stat #{path}")
52
+ command.append_arg('-c', '%i')
53
+
54
+ execute_shell(command)
55
+ command.success?
56
+ end
57
+
58
+ def file_type?(path, type)
59
+ command = Kanrisuru::Command.new("stat #{path}")
60
+ command.append_arg('-c', '%F')
61
+
62
+ execute(command)
63
+
64
+ result = Kanrisuru::Result.new(command, &:to_s)
65
+
66
+ result.success? ? result.data == type : false
67
+ end
68
+
69
+ def stat(path, opts = {})
70
+ follow = opts[:follow]
71
+
72
+ command = Kanrisuru::Command.new('stat')
73
+ command.append_flag('-L', follow)
74
+ command.append_arg('-c', '%A,%b,%D,%F,%g,%G,%h,%i,%n,%s,%u,%U,%x,%y,%z')
75
+ command << path
76
+
77
+ execute(command)
78
+
79
+ Kanrisuru::Result.new(command) do |cmd|
80
+ string = cmd.to_s
81
+ values = string.split(',')
82
+
83
+ FileStat.new(
84
+ Kanrisuru::Mode.new(values[0]),
85
+ values[1].to_i,
86
+ values[2],
87
+ values[3],
88
+ values[4].to_i,
89
+ values[5],
90
+ values[6].to_i,
91
+ values[7].to_i,
92
+ values[8],
93
+ values[9].to_i,
94
+ values[10].to_i,
95
+ values[11],
96
+ values[12] ? DateTime.parse(values[12]) : nil,
97
+ values[13] ? DateTime.parse(values[13]) : nil,
98
+ values[14] ? DateTime.parse(values[14]) : nil
99
+ )
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end