kanrisuru 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +17 -0
- data/.rubocop.yml +47 -0
- data/.rubocop_todo.yml +0 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +2 -5
- data/LICENSE.txt +1 -1
- data/README.md +143 -7
- data/Rakefile +5 -3
- data/bin/console +4 -3
- data/kanrisuru.gemspec +21 -12
- data/lib/kanrisuru.rb +41 -2
- data/lib/kanrisuru/command.rb +99 -0
- data/lib/kanrisuru/core.rb +53 -0
- data/lib/kanrisuru/core/archive.rb +154 -0
- data/lib/kanrisuru/core/disk.rb +302 -0
- data/lib/kanrisuru/core/file.rb +332 -0
- data/lib/kanrisuru/core/find.rb +108 -0
- data/lib/kanrisuru/core/group.rb +97 -0
- data/lib/kanrisuru/core/ip.rb +1032 -0
- data/lib/kanrisuru/core/mount.rb +138 -0
- data/lib/kanrisuru/core/path.rb +140 -0
- data/lib/kanrisuru/core/socket.rb +168 -0
- data/lib/kanrisuru/core/stat.rb +104 -0
- data/lib/kanrisuru/core/stream.rb +121 -0
- data/lib/kanrisuru/core/system.rb +348 -0
- data/lib/kanrisuru/core/transfer.rb +203 -0
- data/lib/kanrisuru/core/user.rb +198 -0
- data/lib/kanrisuru/logger.rb +8 -0
- data/lib/kanrisuru/mode.rb +277 -0
- data/lib/kanrisuru/os_package.rb +235 -0
- data/lib/kanrisuru/remote.rb +10 -0
- data/lib/kanrisuru/remote/cluster.rb +95 -0
- data/lib/kanrisuru/remote/cpu.rb +68 -0
- data/lib/kanrisuru/remote/env.rb +33 -0
- data/lib/kanrisuru/remote/file.rb +354 -0
- data/lib/kanrisuru/remote/fstab.rb +412 -0
- data/lib/kanrisuru/remote/host.rb +191 -0
- data/lib/kanrisuru/remote/memory.rb +19 -0
- data/lib/kanrisuru/remote/os.rb +87 -0
- data/lib/kanrisuru/result.rb +78 -0
- data/lib/kanrisuru/template.rb +32 -0
- data/lib/kanrisuru/util.rb +40 -0
- data/lib/kanrisuru/util/bits.rb +203 -0
- data/lib/kanrisuru/util/fs_mount_opts.rb +655 -0
- data/lib/kanrisuru/util/os_family.rb +213 -0
- data/lib/kanrisuru/util/signal.rb +161 -0
- data/lib/kanrisuru/version.rb +3 -1
- data/spec/functional/core/archive_spec.rb +228 -0
- data/spec/functional/core/disk_spec.rb +80 -0
- data/spec/functional/core/file_spec.rb +341 -0
- data/spec/functional/core/find_spec.rb +52 -0
- data/spec/functional/core/group_spec.rb +65 -0
- data/spec/functional/core/ip_spec.rb +71 -0
- data/spec/functional/core/path_spec.rb +93 -0
- data/spec/functional/core/socket_spec.rb +31 -0
- data/spec/functional/core/stat_spec.rb +98 -0
- data/spec/functional/core/stream_spec.rb +99 -0
- data/spec/functional/core/system_spec.rb +96 -0
- data/spec/functional/core/transfer_spec.rb +108 -0
- data/spec/functional/core/user_spec.rb +76 -0
- data/spec/functional/os_package_spec.rb +75 -0
- data/spec/functional/remote/cluster_spec.rb +45 -0
- data/spec/functional/remote/cpu_spec.rb +41 -0
- data/spec/functional/remote/env_spec.rb +36 -0
- data/spec/functional/remote/fstab_spec.rb +76 -0
- data/spec/functional/remote/host_spec.rb +68 -0
- data/spec/functional/remote/memory_spec.rb +29 -0
- data/spec/functional/remote/os_spec.rb +63 -0
- data/spec/functional/remote/remote_file_spec.rb +180 -0
- data/spec/helper/test_hosts.rb +68 -0
- data/spec/hosts.json +92 -0
- data/spec/spec_helper.rb +11 -3
- data/spec/unit/fstab_spec.rb +22 -0
- data/spec/unit/kanrisuru_spec.rb +9 -0
- data/spec/unit/mode_spec.rb +183 -0
- data/spec/unit/template_spec.rb +13 -0
- data/spec/unit/util_spec.rb +177 -0
- data/spec/zz_reboot_spec.rb +46 -0
- metadata +136 -13
- data/spec/kanrisuru_spec.rb +0 -9
@@ -0,0 +1,203 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Kanrisuru
|
6
|
+
module Core
|
7
|
+
module Transfer
|
8
|
+
extend OsPackage::Define
|
9
|
+
|
10
|
+
os_define :linux, :download
|
11
|
+
os_define :linux, :upload
|
12
|
+
os_define :linux, :wget
|
13
|
+
|
14
|
+
WGET_FILENAME_MODES = %w[unix windows nocontrol ascii lowercase uppercase].freeze
|
15
|
+
WGET_SSL_PROTO = %w[auto SSLv2 SSLv3 TLSv1].freeze
|
16
|
+
|
17
|
+
def download(remote_path, local_path = nil, opts = {})
|
18
|
+
if local_path.instance_of?(Hash)
|
19
|
+
opts = local_path
|
20
|
+
local_path = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
tmp_path = "/tmp/kanrisuru-tmp-#{Time.now.to_i}-#{object_id}"
|
24
|
+
|
25
|
+
begin
|
26
|
+
result = cp(remote_path, tmp_path, force: true)
|
27
|
+
raise 'Unable to copy remote file to temp path' unless result.success?
|
28
|
+
|
29
|
+
result = ssh.scp.download!(tmp_path, local_path, opts)
|
30
|
+
Kanrisuru::Util.blank?(local_path) ? result : local_path
|
31
|
+
ensure
|
32
|
+
rm(tmp_path, force: true) if inode?(tmp_path)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def upload(local_path, remote_path, opts = {})
|
37
|
+
tmp_path = "/tmp/kanrisuru-tmp-#{Time.now.to_i}-#{object_id}"
|
38
|
+
|
39
|
+
begin
|
40
|
+
result = ssh.scp.upload!(local_path, tmp_path, opts)
|
41
|
+
raise 'Unable to upload file' unless result
|
42
|
+
|
43
|
+
result = mv(tmp_path, remote_path)
|
44
|
+
raise 'Unable to move file to remote path' unless result.success?
|
45
|
+
|
46
|
+
stat(remote_path)
|
47
|
+
ensure
|
48
|
+
rm(tmp_path, force: true) if inode?(tmp_path)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def wget(url, opts = {})
|
53
|
+
command = Kanrisuru::Command.new('wget')
|
54
|
+
|
55
|
+
## Logging and input
|
56
|
+
command.append_flag('--quiet', opts[:quiet])
|
57
|
+
|
58
|
+
case opts[:verbose]
|
59
|
+
when true
|
60
|
+
command.append_flag('--verbose')
|
61
|
+
when false
|
62
|
+
command.append_flag('--no-verbose')
|
63
|
+
end
|
64
|
+
|
65
|
+
command.append_arg('--output-file', opts[:log_file])
|
66
|
+
command.append_arg('--append-output', opts[:append_log_file])
|
67
|
+
|
68
|
+
## Download
|
69
|
+
command.append_arg('--bind-address', opts[:bind_address])
|
70
|
+
command.append_arg('--tries', opts[:retries])
|
71
|
+
command.append_arg('--output-document', opts[:output_document])
|
72
|
+
command.append_flag('--no-clobber', opts[:no_clobber])
|
73
|
+
command.append_flag('--continue', opts[:continue])
|
74
|
+
command.append_flag('--server-response', opts[:server_response])
|
75
|
+
command.append_flag('--spider', opts[:spider])
|
76
|
+
command.append_arg('--timeout', opts[:timeout])
|
77
|
+
command.append_arg('--dns-timeout', opts[:dns_timeout])
|
78
|
+
command.append_arg('--connect-timeout', opts[:connect_timeout])
|
79
|
+
command.append_arg('--read-timeout', opts[:read_timeout])
|
80
|
+
command.append_arg('--limit-rate', opts[:limit_rate])
|
81
|
+
command.append_arg('--wait', opts[:wait])
|
82
|
+
command.append_arg('--waitretry', opts[:waitretry])
|
83
|
+
command.append_flag('--random-wait', opts[:random_wait])
|
84
|
+
command.append_flag('--no-proxy', opts[:no_proxy])
|
85
|
+
command.append_flag('--no-dns-cache', opts[:no_dns_cache])
|
86
|
+
|
87
|
+
command.append_arg('--quota', opts[:quota])
|
88
|
+
|
89
|
+
if Kanrisuru::Util.present?(opts[:restrict_file_names])
|
90
|
+
command.append_arg('--restrict-file-names', Kanrisuru::Util.string_join_array(opts[:restrict_file_names]))
|
91
|
+
end
|
92
|
+
|
93
|
+
case opts[:family]
|
94
|
+
when 'inet'
|
95
|
+
command.append_flag('--inet4-only')
|
96
|
+
when 'inet6'
|
97
|
+
command.append_flag('--inet6-only')
|
98
|
+
end
|
99
|
+
|
100
|
+
command.append_flag('--retry-connrefused', opts[:retry_connrefused])
|
101
|
+
command.append_arg('--user', opts[:user])
|
102
|
+
command.append_arg('--password', opts[:password])
|
103
|
+
command.append_flag('--no-iri', opts[:no_iri])
|
104
|
+
command.append_arg('--local-encoding', opts[:local_encoding])
|
105
|
+
command.append_arg('--remote-encoding', opts[:remote_encoding])
|
106
|
+
|
107
|
+
## Directories
|
108
|
+
command.append_flag('--no-directories', opts[:no_directories])
|
109
|
+
command.append_flag('--force-directories', opts[:force_directories])
|
110
|
+
command.append_flag('--no-host-directories', opts[:no_host_directories])
|
111
|
+
command.append_flag('--protocol-directories', opts[:protocol_directories])
|
112
|
+
command.append_arg('--cut-dirs', opts[:cut_dirs])
|
113
|
+
command.append_arg('--directory-prefix', opts[:directory_prefix])
|
114
|
+
|
115
|
+
## HTTP
|
116
|
+
command.append_arg('--default-page', opts[:default_page])
|
117
|
+
command.append_flag('--adjust-extension', opts[:adjust_extension])
|
118
|
+
command.append_arg('--http-user', opts[:http_user])
|
119
|
+
command.append_arg('--http-password', opts[:http_password])
|
120
|
+
command.append_arg('--load-cookies', opts[:load_cookies])
|
121
|
+
command.append_arg('--save-cookies', opts[:save_cookies])
|
122
|
+
command.append_flag('--no-http-keep-alive', opts[:no_http_keep_alive])
|
123
|
+
command.append_flag('--no-cache', opts[:no_cache])
|
124
|
+
command.append_flag('--no-cookies', opts[:no_cookies])
|
125
|
+
command.append_flag('--keep-session-cookies', opts[:keep_session_cookies])
|
126
|
+
command.append_flag('--ignore-length', opts[:ignore_length])
|
127
|
+
command.append_arg('--header', opts[:header])
|
128
|
+
command.append_arg('--max-redirect', opts[:max_redirect])
|
129
|
+
command.append_arg('--proxy-user', opts[:proxy_user])
|
130
|
+
command.append_arg('--proxy-password', opts[:proxy_password])
|
131
|
+
command.append_arg('--referer', opts[:referer])
|
132
|
+
command.append_flag('--save-headers', opts[:save_headers])
|
133
|
+
command.append_arg('--user-agent', opts[:user_agent])
|
134
|
+
|
135
|
+
post_data = opts[:post_data]
|
136
|
+
|
137
|
+
if Kanrisuru::Util.present?(post_data)
|
138
|
+
post_data = post_data.instance_of?(Hash) ? URI.encode_www_form(post_data) : post_data
|
139
|
+
command.append_arg('--post-data', post_data)
|
140
|
+
end
|
141
|
+
|
142
|
+
command.append_arg('--post-file', opts[:post_file])
|
143
|
+
command.append_flag('--content-disposition', opts[:content_disposition])
|
144
|
+
|
145
|
+
## SSL / TLS
|
146
|
+
if Kanrisuru::Util.present?(opts[:secure_protocol])
|
147
|
+
raise ArgumentError, 'invalid ssl protocol' unless WGET_SSL_PROTO.include?(opts[:secure_protocol])
|
148
|
+
|
149
|
+
command.append_arg('--secure-protocol', opts[:secure_protocol])
|
150
|
+
end
|
151
|
+
|
152
|
+
command.append_flag('--no-check-certificate', opts[:no_check_certificate])
|
153
|
+
command.append_arg('--certificate', opts[:certificate])
|
154
|
+
command.append_arg('--certificate-type', opts[:certificate_type])
|
155
|
+
command.append_arg('--private-key', opts[:private_key])
|
156
|
+
command.append_arg('--private-key-type', opts[:private_key_type])
|
157
|
+
command.append_arg('--ca-certificate', opts[:ca_certificate])
|
158
|
+
command.append_arg('--ca-directory', opts[:ca_directory])
|
159
|
+
command.append_arg('--random-file', opts[:random_file])
|
160
|
+
command.append_arg('--egd-file', opts[:egd_file])
|
161
|
+
|
162
|
+
## FTP
|
163
|
+
command.append_arg('--ftp-user', opts[:ftp_user])
|
164
|
+
command.append_arg('--ftp-password', opts[:ftp_password])
|
165
|
+
command.append_flag('--no-remove-listing', opts[:no_remove_listing])
|
166
|
+
command.append_flag('--no-glob', opts[:no_glob])
|
167
|
+
command.append_flag('--no-passive-ftp', opts[:no_passive_ftp])
|
168
|
+
command.append_flag('--retr-symlinks', opts[:retr_symlinks])
|
169
|
+
|
170
|
+
## Recursive Retrieval
|
171
|
+
command.append_flag('--recursive', opts[:recursive])
|
172
|
+
command.append_arg('--level', opts[:depth])
|
173
|
+
command.append_flag('--delete-after', opts[:delete_after])
|
174
|
+
command.append_flag('--convert-links', opts[:convert_links])
|
175
|
+
command.append_flag('--backup-converted', opts[:backup_converted])
|
176
|
+
command.append_flag('--mirror', opts[:mirror])
|
177
|
+
command.append_flag('--page-requisites', opts[:page_requisites])
|
178
|
+
command.append_flag('--strict-comments', opts[:strict_comments])
|
179
|
+
|
180
|
+
## Recursive Accept/Reject
|
181
|
+
command.append_arg('--accept', Kanrisuru::Util.array_join_string(opts[:accept_list]))
|
182
|
+
command.append_arg('--reject', Kanrisuru::Util.array_join_string(opts[:reject_list]))
|
183
|
+
command.append_arg('--domains', Kanrisuru::Util.array_join_string(opts[:domain_list]))
|
184
|
+
command.append_arg('--exclude-domains', Kanrisuru::Util.array_join_string(opts[:exclude_domain_list]))
|
185
|
+
command.append_arg('--follow-tags', Kanrisuru::Util.array_join_string(opts[:follow_tags]))
|
186
|
+
command.append_arg('--ignore-tags', Kanrisuru::Util.array_join_string(opts[:ignore_tags]))
|
187
|
+
command.append_arg('--include-directories', Kanrisuru::Util.array_join_string(opts[:include_directories]))
|
188
|
+
command.append_arg('--exclude-directories', Kanrisuru::Util.array_join_string(opts[:exclude_directories]))
|
189
|
+
command.append_flag('--follow-ftp', opts[:follow_ftp])
|
190
|
+
command.append_flag('--ignore-case', opts[:ignore_case])
|
191
|
+
command.append_flag('--span-hosts', opts[:span_hosts])
|
192
|
+
command.append_flag('--relative', opts[:relative])
|
193
|
+
command.append_flag('--no-parent', opts[:no_parent])
|
194
|
+
|
195
|
+
command << url
|
196
|
+
|
197
|
+
execute_shell(command)
|
198
|
+
|
199
|
+
Kanrisuru::Result.new(command)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kanrisuru
|
4
|
+
module Core
|
5
|
+
module User
|
6
|
+
extend OsPackage::Define
|
7
|
+
|
8
|
+
os_define :linux, :user?
|
9
|
+
os_define :linux, :get_uid
|
10
|
+
os_define :linux, :get_user
|
11
|
+
os_define :linux, :create_user
|
12
|
+
os_define :linux, :update_user
|
13
|
+
os_define :linux, :delete_user
|
14
|
+
|
15
|
+
User = Struct.new(:uid, :name, :home, :shell, :groups)
|
16
|
+
UserGroup = Struct.new(:gid, :name)
|
17
|
+
FilePath = Struct.new(:path)
|
18
|
+
|
19
|
+
def user?(user)
|
20
|
+
result = get_uid(user)
|
21
|
+
return false if result.failure?
|
22
|
+
|
23
|
+
Kanrisuru::Util.present?(result.data) && result.data.instance_of?(Integer)
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_uid(user)
|
27
|
+
command = Kanrisuru::Command.new("id -u #{user}")
|
28
|
+
|
29
|
+
execute(command)
|
30
|
+
|
31
|
+
Kanrisuru::Result.new(command, &:to_i)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_user(user)
|
35
|
+
command = Kanrisuru::Command.new("id #{user}")
|
36
|
+
execute_shell(command)
|
37
|
+
|
38
|
+
Kanrisuru::Result.new(command) do |cmd|
|
39
|
+
## Get user id
|
40
|
+
result = get_uid(user)
|
41
|
+
break if result.failure?
|
42
|
+
|
43
|
+
uid = result.to_i
|
44
|
+
|
45
|
+
## Get all groups for the user, with gid and group name
|
46
|
+
string = cmd.to_s
|
47
|
+
string = string.split('groups=')[1]
|
48
|
+
array = string.gsub(/\(/, '').gsub(/\)/, '').split(',')
|
49
|
+
|
50
|
+
groups = array.map do |str|
|
51
|
+
gid = str.delete('^0-9').to_i
|
52
|
+
name = str.delete('0-9')
|
53
|
+
|
54
|
+
UserGroup.new(gid, name)
|
55
|
+
end
|
56
|
+
|
57
|
+
## Get home / shell path information
|
58
|
+
cmd = Kanrisuru::Command.new("getent passwd #{user}")
|
59
|
+
cmd | "awk -F: '{print $6, $7}'"
|
60
|
+
|
61
|
+
execute(cmd)
|
62
|
+
|
63
|
+
result = Kanrisuru::Result.new(cmd) do |cmd2|
|
64
|
+
cmd2.to_s.split.map { |value| FilePath.new(value) }
|
65
|
+
end
|
66
|
+
|
67
|
+
## TODO: Raise custom error to change parent result to use nested error and mark
|
68
|
+
## as failure.
|
69
|
+
break if result.failure?
|
70
|
+
|
71
|
+
home = result[0]
|
72
|
+
shell = result[1]
|
73
|
+
|
74
|
+
User.new(uid, user, home, shell, groups)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_user(user, opts = {})
|
79
|
+
uid = opts[:uid]
|
80
|
+
group = opts[:group]
|
81
|
+
groups = opts[:groups]
|
82
|
+
home = opts[:home]
|
83
|
+
shell = opts[:shell] || '/bin/false'
|
84
|
+
createhome = opts[:createhome]
|
85
|
+
system_opt = opts[:system]
|
86
|
+
skeleton = opts[:skeleton]
|
87
|
+
non_unique = opts[:non_unique]
|
88
|
+
password = opts[:password]
|
89
|
+
expires = opts[:expires] ## YYYY-MM-DD
|
90
|
+
|
91
|
+
command = Kanrisuru::Command.new("useradd #{user}")
|
92
|
+
|
93
|
+
if Kanrisuru::Util.present?(uid)
|
94
|
+
command.append_arg('-u', uid)
|
95
|
+
command.append_flag('-o', non_unique)
|
96
|
+
end
|
97
|
+
|
98
|
+
command.append_flag('-r', system_opt)
|
99
|
+
command.append_arg('-s', shell)
|
100
|
+
command.append_arg('-d', home)
|
101
|
+
|
102
|
+
case createhome
|
103
|
+
when true
|
104
|
+
command.append_flag('-m')
|
105
|
+
command.append_arg('-k', skeleton)
|
106
|
+
when false
|
107
|
+
command.append_flag('-M')
|
108
|
+
end
|
109
|
+
|
110
|
+
if Kanrisuru::Util.present?(group) && group?(group)
|
111
|
+
command.append_arg('-g', group)
|
112
|
+
elsif group?(user)
|
113
|
+
command.append_flag('-N')
|
114
|
+
end
|
115
|
+
|
116
|
+
command.append_arg('-G', groups.join(',')) if Kanrisuru::Util.present?(groups)
|
117
|
+
|
118
|
+
command.append_arg('-p', password)
|
119
|
+
command.append_arg('-e', expires)
|
120
|
+
|
121
|
+
execute_shell(command)
|
122
|
+
|
123
|
+
Kanrisuru::Result.new(command) do
|
124
|
+
get_user(user).data
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def update_user(user, opts = {})
|
129
|
+
uid = opts[:uid]
|
130
|
+
group = opts[:group]
|
131
|
+
groups = opts[:groups]
|
132
|
+
append = opts[:append]
|
133
|
+
home = opts[:home]
|
134
|
+
move_home = opts[:move_home]
|
135
|
+
shell = opts[:shell] || '/bin/false'
|
136
|
+
non_unique = opts[:non_unique]
|
137
|
+
password = opts[:password]
|
138
|
+
expires = opts[:expires] ## YYYY-MM-DD
|
139
|
+
locked = opts[:locked]
|
140
|
+
|
141
|
+
command = Kanrisuru::Command.new("usermod #{user}")
|
142
|
+
|
143
|
+
if Kanrisuru::Util.present?(home)
|
144
|
+
command.append_arg('-d', home)
|
145
|
+
command.append_flag('-m', move_home)
|
146
|
+
end
|
147
|
+
|
148
|
+
command.append_arg('-s', shell)
|
149
|
+
|
150
|
+
if Kanrisuru::Util.present?(uid)
|
151
|
+
command.append_arg('-u', uid)
|
152
|
+
command.append_flag('-o', non_unique)
|
153
|
+
end
|
154
|
+
|
155
|
+
command.append_arg('-g', group) if Kanrisuru::Util.present?(group) && group_exists?(group)
|
156
|
+
|
157
|
+
if Kanrisuru::Util.present?(groups)
|
158
|
+
command.append_arg('-G', groups.join(','))
|
159
|
+
command.append_flag('-a', append)
|
160
|
+
end
|
161
|
+
|
162
|
+
case locked
|
163
|
+
when true
|
164
|
+
command.append_flag('-L')
|
165
|
+
command.append_arg('-e', 1)
|
166
|
+
when false
|
167
|
+
command.append_arg('-U')
|
168
|
+
command.append_arg('-e', 99_999)
|
169
|
+
else
|
170
|
+
## Ensure expires isn't added twice.
|
171
|
+
command.append_arg('-e', expires)
|
172
|
+
|
173
|
+
## Can't use password with lock / unlock flag.
|
174
|
+
command.append_arg('-p', password)
|
175
|
+
end
|
176
|
+
|
177
|
+
execute_shell(command)
|
178
|
+
|
179
|
+
Kanrisuru::Result.new(command) do |_command|
|
180
|
+
get_user(user).data
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def delete_user(user, opts = {})
|
185
|
+
force = opts[:force]
|
186
|
+
|
187
|
+
return false unless get_uid(user)
|
188
|
+
|
189
|
+
command = Kanrisuru::Command.new("userdel #{user}")
|
190
|
+
command.append_flag('-f', force)
|
191
|
+
|
192
|
+
execute_shell(command)
|
193
|
+
|
194
|
+
Kanrisuru::Result.new(command)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,277 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kanrisuru
|
4
|
+
class Mode
|
5
|
+
class Permission
|
6
|
+
attr_reader :symbolic
|
7
|
+
|
8
|
+
def initialize(numeric, symbolic)
|
9
|
+
@numeric = numeric
|
10
|
+
@symbolic = symbolic
|
11
|
+
|
12
|
+
update_symbolic_rwx
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_i
|
16
|
+
numeric.to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
symbolic
|
21
|
+
end
|
22
|
+
|
23
|
+
def numeric
|
24
|
+
@numeric.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def all?
|
28
|
+
read? && write? && execute?
|
29
|
+
end
|
30
|
+
|
31
|
+
def symbolic=(symbolic)
|
32
|
+
@symbolic = symbolic
|
33
|
+
|
34
|
+
update_symbolic_rwx
|
35
|
+
update_numeric
|
36
|
+
end
|
37
|
+
|
38
|
+
def numeric=(numeric)
|
39
|
+
@numeric = numeric
|
40
|
+
|
41
|
+
update_numeric_rwx
|
42
|
+
update_symbolic
|
43
|
+
end
|
44
|
+
|
45
|
+
def read=(boolean)
|
46
|
+
@readable = boolean
|
47
|
+
|
48
|
+
update_numeric
|
49
|
+
update_symbolic
|
50
|
+
end
|
51
|
+
|
52
|
+
def write=(boolean)
|
53
|
+
@writeable = boolean
|
54
|
+
|
55
|
+
update_numeric
|
56
|
+
update_symbolic
|
57
|
+
end
|
58
|
+
|
59
|
+
def execute=(boolean)
|
60
|
+
@executable = boolean
|
61
|
+
|
62
|
+
update_numeric
|
63
|
+
update_symbolic
|
64
|
+
end
|
65
|
+
|
66
|
+
def read?
|
67
|
+
@readable
|
68
|
+
end
|
69
|
+
|
70
|
+
def write?
|
71
|
+
@writeable
|
72
|
+
end
|
73
|
+
|
74
|
+
def execute?
|
75
|
+
@executable
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def update_symbolic_rwx
|
81
|
+
@readable = @symbolic.include?('r')
|
82
|
+
@writeable = @symbolic.include?('w')
|
83
|
+
@executable = @symbolic.include?('x')
|
84
|
+
end
|
85
|
+
|
86
|
+
def update_numeric_rwx
|
87
|
+
mode = @numeric.to_i(8)
|
88
|
+
|
89
|
+
@readable = ((mode >> 2) & 0b001) == 1
|
90
|
+
@writeable = ((mode >> 1) & 0b001) == 1
|
91
|
+
@executable = ((mode >> 0) & 0b001) == 1
|
92
|
+
end
|
93
|
+
|
94
|
+
def update_numeric
|
95
|
+
@numeric = (((read? ? 1 : 0) << 2) + ((write? ? 1 : 0) << 1) + (execute? ? 1 : 0)).to_s
|
96
|
+
end
|
97
|
+
|
98
|
+
def update_symbolic
|
99
|
+
@symbolic = "#{read? ? 'r' : '-'}#{write? ? 'w' : '-'}#{execute? ? 'x' : '-'}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
attr_reader :owner, :group, :other
|
104
|
+
|
105
|
+
def initialize(mode)
|
106
|
+
if mode.instance_of?(Integer)
|
107
|
+
init_mode(mode.to_s(8))
|
108
|
+
elsif mode.instance_of?(String)
|
109
|
+
init_mode(mode)
|
110
|
+
else
|
111
|
+
raise 'Invalid mode type'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def directory?
|
116
|
+
@directory == 'd'
|
117
|
+
end
|
118
|
+
|
119
|
+
def symbolic
|
120
|
+
@directory + @owner.symbolic + @group.symbolic + @other.symbolic
|
121
|
+
end
|
122
|
+
|
123
|
+
def symbolic=(string)
|
124
|
+
raise ArgumentErorr, 'Invalid symbolic type' if string.class != String
|
125
|
+
|
126
|
+
if string.length == 10 && !string.include?(',')
|
127
|
+
modes = string[1..-1]
|
128
|
+
|
129
|
+
@owner.symbolic = modes[0..2]
|
130
|
+
@group.symbolic = modes[3..5]
|
131
|
+
@other.symbolic = modes[6..8]
|
132
|
+
else
|
133
|
+
operations = string.split(',')
|
134
|
+
operations.each do |operation|
|
135
|
+
flags = operation.split(/[=+-]/)
|
136
|
+
|
137
|
+
commands = flags[0] == '' ? 'a' : flags[0]
|
138
|
+
fields = flags[1]
|
139
|
+
|
140
|
+
commands = commands.chars
|
141
|
+
|
142
|
+
commands.each do |command|
|
143
|
+
case command
|
144
|
+
when 'a'
|
145
|
+
apply_operation(operation, fields, @owner)
|
146
|
+
apply_operation(operation, fields, @group)
|
147
|
+
apply_operation(operation, fields, @other)
|
148
|
+
when 'u'
|
149
|
+
apply_operation(operation, fields, @owner)
|
150
|
+
when 'g'
|
151
|
+
apply_operation(operation, fields, @group)
|
152
|
+
when 'o'
|
153
|
+
apply_operation(operation, fields, @other)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def numeric
|
161
|
+
@owner.numeric + @group.numeric + @other.numeric
|
162
|
+
end
|
163
|
+
|
164
|
+
def numeric=(numeric)
|
165
|
+
string =
|
166
|
+
if numeric.instance_of?(Integer)
|
167
|
+
numeric.to_s(8)
|
168
|
+
else
|
169
|
+
numeric
|
170
|
+
end
|
171
|
+
|
172
|
+
tokens = string.chars
|
173
|
+
|
174
|
+
@owner.numeric = tokens[0]
|
175
|
+
@group.numeric = tokens[1]
|
176
|
+
@other.numeric = tokens[2]
|
177
|
+
end
|
178
|
+
|
179
|
+
def inspect
|
180
|
+
format('#<Kanrisuru::Mode:0x%<object_id>s @numeric=%<numeric>s @symbolic=%<symbolic>s>',
|
181
|
+
object_id: object_id, numeric: numeric, symbolic: symbolic)
|
182
|
+
end
|
183
|
+
|
184
|
+
def to_s
|
185
|
+
symbolic
|
186
|
+
end
|
187
|
+
|
188
|
+
def to_i
|
189
|
+
numeric.to_i(8)
|
190
|
+
end
|
191
|
+
|
192
|
+
private
|
193
|
+
|
194
|
+
def apply_operation(operation, fields, permission)
|
195
|
+
if operation.include?('=')
|
196
|
+
remaining_fields = 'rwx'
|
197
|
+
|
198
|
+
fields.chars.each do |field|
|
199
|
+
apply_field_to_permission(field, permission, true)
|
200
|
+
|
201
|
+
## remove any field that shouldn't be set to false
|
202
|
+
remaining_fields = remaining_fields.gsub(field, '')
|
203
|
+
end
|
204
|
+
|
205
|
+
## Apply false to any remaining fields
|
206
|
+
apply_field_to_permission(remaining_fields, permission, false)
|
207
|
+
elsif operation.include?('-')
|
208
|
+
apply_field_to_permission(fields, permission, false)
|
209
|
+
elsif operation.include?('+')
|
210
|
+
apply_field_to_permission(fields, permission, true)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def apply_field_to_permission(fields, permission, boolean)
|
215
|
+
permission.read = boolean if fields.include?('r')
|
216
|
+
permission.write = boolean if fields.include?('w')
|
217
|
+
permission.execute = boolean if fields.include?('x')
|
218
|
+
end
|
219
|
+
|
220
|
+
def init_mode(string)
|
221
|
+
string = parse_acl(string)
|
222
|
+
|
223
|
+
if string.length == 3
|
224
|
+
@directory = '-'
|
225
|
+
tokens = string.chars
|
226
|
+
|
227
|
+
@owner = Kanrisuru::Mode::Permission.new(tokens[0], numeric_to_symbolic(tokens[0].to_i))
|
228
|
+
@group = Kanrisuru::Mode::Permission.new(tokens[1], numeric_to_symbolic(tokens[1].to_i))
|
229
|
+
@other = Kanrisuru::Mode::Permission.new(tokens[2], numeric_to_symbolic(tokens[2].to_i))
|
230
|
+
elsif string.length == 10 && !string.include?(',')
|
231
|
+
@directory = string[0]
|
232
|
+
modes = string[1..-1]
|
233
|
+
|
234
|
+
@owner = Kanrisuru::Mode::Permission.new(symbolic_to_numeric(modes[0..2]), modes[0..2])
|
235
|
+
@group = Kanrisuru::Mode::Permission.new(symbolic_to_numeric(modes[3..5]), modes[3..5])
|
236
|
+
@other = Kanrisuru::Mode::Permission.new(symbolic_to_numeric(modes[6..8]), modes[6..8])
|
237
|
+
else
|
238
|
+
raise ArgumentErorr, "Invalid format for mode #{string}"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def parse_acl(string)
|
243
|
+
@acl = string[-1] == '.' ? 'selinux' : 'general'
|
244
|
+
string.gsub(/[.+]/, '')
|
245
|
+
end
|
246
|
+
|
247
|
+
def symbolic_to_numeric(ref)
|
248
|
+
conversions = {
|
249
|
+
'---' => 0,
|
250
|
+
'---x' => 1,
|
251
|
+
'-w-' => 2,
|
252
|
+
'-wx' => 3,
|
253
|
+
'r--' => 4,
|
254
|
+
'r-x' => 5,
|
255
|
+
'rw-' => 6,
|
256
|
+
'rwx' => 7
|
257
|
+
}
|
258
|
+
|
259
|
+
conversions[ref]
|
260
|
+
end
|
261
|
+
|
262
|
+
def numeric_to_symbolic(int)
|
263
|
+
conversions = {
|
264
|
+
0 => '---',
|
265
|
+
1 => '--x',
|
266
|
+
2 => '-w-',
|
267
|
+
3 => '-wx',
|
268
|
+
4 => 'r--',
|
269
|
+
5 => 'r-x',
|
270
|
+
6 => 'rw-',
|
271
|
+
7 => 'rwx'
|
272
|
+
}
|
273
|
+
|
274
|
+
conversions[int]
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|