hatecf 0.1.1 → 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.
- checksums.yaml +4 -4
- data/bootstrap_ruby +1 -1
- data/lib/local.rb +28 -11
- data/lib/local_dsl.rb +13 -5
- data/remote/remote.rb +26 -12
- data/remote/remote_dsl.rb +6 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9dac6ef08ee3123c1815d6e8381147f8927693400da455086562073f14c591e3
|
|
4
|
+
data.tar.gz: acdf885dc3fe9ef1689ec14249c6a30ce13281c1839dd8ceacaa8856b10e4d25
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5852eca0446e36b759683599ae8005e97cf12e8404160001078199388a7dedbbb78831340b486b63e3e5b01a677501d84f81f0eef61fd4cb22a8e7e20477f7f4
|
|
7
|
+
data.tar.gz: 245aaa98f3ae07c4bc7b7802969a2aa61ea7334815245dadc23911d5c3fc70de294eaf8617762a2e7bb74dfdd7f077a6817096e003238ceff89e6b2691e90b13
|
data/bootstrap_ruby
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
|
-
|
|
2
|
+
which ruby > /dev/null || (echo "machine has no ruby; installing..."; apt-get install --no-install-recommends -y ruby)
|
data/lib/local.rb
CHANGED
|
@@ -18,9 +18,12 @@ module Local
|
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
attr_accessor :really_die
|
|
22
|
+
@really_die = false
|
|
21
23
|
def die(message)
|
|
22
24
|
$stderr.puts "Script error: #{message}"
|
|
23
25
|
print_location
|
|
26
|
+
@really_die = true
|
|
24
27
|
exit 1
|
|
25
28
|
end
|
|
26
29
|
|
|
@@ -66,9 +69,11 @@ module Local
|
|
|
66
69
|
@local_files = []
|
|
67
70
|
|
|
68
71
|
require 'pathname'
|
|
72
|
+
# TODO: we are not able to copy directories with this,
|
|
73
|
+
# but we should be
|
|
69
74
|
def copy_local_files_to(dir)
|
|
70
75
|
@local_files.each do |local_file|
|
|
71
|
-
#
|
|
76
|
+
# duplicating the whole directory structure
|
|
72
77
|
acc = []
|
|
73
78
|
Pathname.new(local_file).each_filename do |chunk|
|
|
74
79
|
source_path = File.join(*(['/'] + acc << chunk))
|
|
@@ -87,14 +92,20 @@ module Local
|
|
|
87
92
|
end
|
|
88
93
|
end
|
|
89
94
|
|
|
95
|
+
@performed = false
|
|
90
96
|
require 'tmpdir'
|
|
91
97
|
def perform!
|
|
98
|
+
return if @performed # just for compatibility with < 0.2
|
|
99
|
+
# when manual invoke of peform! was needed
|
|
92
100
|
die "no target host specified!" if (@target[:host] || "").empty?
|
|
93
|
-
script_path = File.expand_path
|
|
94
|
-
script_dir = File.dirname
|
|
101
|
+
script_path = File.expand_path ENV["_"]
|
|
102
|
+
script_dir = File.dirname script_path
|
|
95
103
|
status = nil
|
|
96
104
|
Dir.mktmpdir "hatecf" do |tmp_dir|
|
|
97
105
|
debug "using temporary dir #{tmp_dir}"
|
|
106
|
+
File.chmod(00755, tmp_dir) # TODO: this is a tiny security issue.
|
|
107
|
+
# We should set these permissions
|
|
108
|
+
# only when we have "as" blocks.
|
|
98
109
|
FileUtils.cp(script_path, File.join(tmp_dir, "script.rb"))
|
|
99
110
|
File.chmod(00777, File.join(tmp_dir, "script.rb"))
|
|
100
111
|
FileUtils.cp(File.join(__dir__, "../remote/hatecf.rb" ), tmp_dir)
|
|
@@ -117,19 +128,25 @@ module Local
|
|
|
117
128
|
pid, status = Process.wait2(Process.spawn(cmd))
|
|
118
129
|
debug "exit status: #{status.exitstatus}"
|
|
119
130
|
end
|
|
131
|
+
@performed = true
|
|
120
132
|
# FIXME: this always returns the status of "; rm" above, doesn't it?
|
|
121
133
|
exit status.exitstatus
|
|
122
134
|
end
|
|
123
135
|
|
|
124
136
|
require 'optparse'
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
begin
|
|
138
|
+
OptionParser.new do |opts|
|
|
139
|
+
opts.on "--dry", "don't change anything, just test everything" do |x|
|
|
140
|
+
@dry_run = true
|
|
141
|
+
end
|
|
142
|
+
opts.on "-v", "verbose mode: print debug messages" do |x|
|
|
143
|
+
@verbose = true
|
|
144
|
+
end
|
|
145
|
+
end.parse!
|
|
146
|
+
rescue OptionParser::InvalidOption => e
|
|
147
|
+
$stderr.puts e
|
|
148
|
+
exit 1
|
|
149
|
+
end
|
|
133
150
|
|
|
134
151
|
def debug(s)
|
|
135
152
|
info s if @verbose
|
data/lib/local_dsl.rb
CHANGED
|
@@ -4,10 +4,14 @@ def target(host:, user: nil, port: nil)
|
|
|
4
4
|
Local.type_check(:host, host, String)
|
|
5
5
|
Local.type_check(:user, user, String) if user
|
|
6
6
|
Local.type_check(:port, port, Integer) if port
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
if Local.target.empty?
|
|
8
|
+
Local.target[:host] = host
|
|
9
|
+
Local.target[:user] = user if user
|
|
10
|
+
Local.target[:port] = port if port
|
|
11
|
+
else
|
|
12
|
+
Local.die "multiple targets not supported (yet, idk)"
|
|
13
|
+
exit 1
|
|
14
|
+
end
|
|
11
15
|
end
|
|
12
16
|
|
|
13
17
|
class LocalFile
|
|
@@ -215,10 +219,14 @@ class RemoteFile
|
|
|
215
219
|
end
|
|
216
220
|
end
|
|
217
221
|
|
|
218
|
-
def perform!
|
|
222
|
+
def perform! # legacy, not needed since 0.2
|
|
219
223
|
Local.perform!
|
|
220
224
|
end
|
|
221
225
|
|
|
226
|
+
Kernel.at_exit do
|
|
227
|
+
Local.perform! unless Local.really_die
|
|
228
|
+
end
|
|
229
|
+
|
|
222
230
|
# Monkey-patching
|
|
223
231
|
|
|
224
232
|
class Array
|
data/remote/remote.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module Remote
|
|
2
2
|
extend self
|
|
3
3
|
|
|
4
|
-
# $HOME variable should be imported from local machine
|
|
5
|
-
# in order to access ~/ paths
|
|
6
|
-
# and directory of
|
|
4
|
+
# $HOME variable should be imported from the local machine
|
|
5
|
+
# in order to access tilda ~/ paths
|
|
6
|
+
# and directory of the script should be imported
|
|
7
7
|
# in order to access relative ./ paths
|
|
8
8
|
attr_accessor :local_home, :local_script_dir
|
|
9
9
|
|
|
@@ -129,6 +129,7 @@ module Remote
|
|
|
129
129
|
end
|
|
130
130
|
|
|
131
131
|
def service_reload(name)
|
|
132
|
+
name = name.to_s
|
|
132
133
|
destructive "reloading service #{name}" do
|
|
133
134
|
cmd = ["systemctl", "reload", name]
|
|
134
135
|
spawn(cmd, expect_status: 0)
|
|
@@ -136,6 +137,7 @@ module Remote
|
|
|
136
137
|
end
|
|
137
138
|
|
|
138
139
|
def service_restart(name)
|
|
140
|
+
name = name.to_s
|
|
139
141
|
destructive "restarting service #{name}" do
|
|
140
142
|
cmd = ["systemctl", "restart", name]
|
|
141
143
|
spawn(cmd, expect_status: 0)
|
|
@@ -163,6 +165,8 @@ module Remote
|
|
|
163
165
|
|
|
164
166
|
def create_user(name, create_home, shell)
|
|
165
167
|
if user_exists?(name)
|
|
168
|
+
# TODO: should we check if existing user
|
|
169
|
+
# has the specified shell?
|
|
166
170
|
ok "#{name} user exists"
|
|
167
171
|
else
|
|
168
172
|
destructive "creating user #{name}" do
|
|
@@ -175,6 +179,7 @@ module Remote
|
|
|
175
179
|
end
|
|
176
180
|
|
|
177
181
|
require 'fileutils'
|
|
182
|
+
# FIXME: even when run "afterwards" it crashes if user doesn't exist.
|
|
178
183
|
def authorize_ssh_key(user, key)
|
|
179
184
|
case key
|
|
180
185
|
when LocalFile
|
|
@@ -220,7 +225,6 @@ module Remote
|
|
|
220
225
|
end
|
|
221
226
|
end
|
|
222
227
|
|
|
223
|
-
attr_accessor :apt_updated
|
|
224
228
|
def dpkg_installed?(names)
|
|
225
229
|
# | virtual | virtual | removed
|
|
226
230
|
# | package | package | but
|
|
@@ -248,6 +252,7 @@ module Remote
|
|
|
248
252
|
end
|
|
249
253
|
end
|
|
250
254
|
|
|
255
|
+
@apt_updated = false
|
|
251
256
|
def apt_install(names)
|
|
252
257
|
names = names.to_s if names.is_a? Symbol
|
|
253
258
|
names = names.split(/\s+/).map(&:strip).select{|x|not x.empty?} if names.is_a? String
|
|
@@ -255,10 +260,10 @@ module Remote
|
|
|
255
260
|
ok "installed: #{names.join(', ')}"
|
|
256
261
|
else
|
|
257
262
|
destructive "apt-get install #{names.join(' ')}" do
|
|
258
|
-
unless apt_updated
|
|
263
|
+
unless @apt_updated
|
|
259
264
|
cmd = ["apt-get", "update", "-q"]
|
|
260
265
|
spawn(cmd, expect_status: 0)
|
|
261
|
-
apt_updated = true
|
|
266
|
+
@apt_updated = true
|
|
262
267
|
end
|
|
263
268
|
|
|
264
269
|
cmd = ["apt-get", "install", "--no-install-recommends", "-y"]
|
|
@@ -277,10 +282,12 @@ module Remote
|
|
|
277
282
|
if installed.empty?
|
|
278
283
|
ok "removed: #{names.join(", ")}"
|
|
279
284
|
else
|
|
285
|
+
# FIXME: eh, what was the logic behind this cycle when I made it?..
|
|
286
|
+
# Why do I need to remove packages one by one?
|
|
280
287
|
installed.each do |name|
|
|
281
288
|
destructive "apt-get remove #{name}" do
|
|
282
289
|
cmd = ["apt-get", "remove", "-y"]
|
|
283
|
-
cmd
|
|
290
|
+
cmd << name
|
|
284
291
|
spawn cmd, expect_status: 0
|
|
285
292
|
end
|
|
286
293
|
end
|
|
@@ -332,7 +339,7 @@ module Remote
|
|
|
332
339
|
|
|
333
340
|
def rm(x)
|
|
334
341
|
x = File.expand_path x
|
|
335
|
-
if File.
|
|
342
|
+
if File.exist? x
|
|
336
343
|
destructive "rm #{x}" do
|
|
337
344
|
FileUtils.rm x
|
|
338
345
|
end
|
|
@@ -341,7 +348,7 @@ module Remote
|
|
|
341
348
|
end
|
|
342
349
|
end
|
|
343
350
|
|
|
344
|
-
# TODO:
|
|
351
|
+
# TODO: handle "dst is a dir" case
|
|
345
352
|
def cp(src, dst, mode)
|
|
346
353
|
src = src.remote_path if src.is_a? LocalFile
|
|
347
354
|
dst = File.expand_path dst
|
|
@@ -376,10 +383,12 @@ module Remote
|
|
|
376
383
|
end
|
|
377
384
|
end
|
|
378
385
|
|
|
386
|
+
# TODO: handle "dst is a dir" case
|
|
387
|
+
# TODO: relative path case
|
|
379
388
|
def ln_s(src, dst)
|
|
380
389
|
src = File.expand_path src
|
|
381
390
|
dst = File.expand_path dst
|
|
382
|
-
if File.exist?(dst) &&File.lstat(dst).symlink? && File.readlink(dst) == src
|
|
391
|
+
if File.exist?(dst) && File.lstat(dst).symlink? && File.readlink(dst) == src
|
|
383
392
|
ok "#{dst} leads to #{src}"
|
|
384
393
|
else
|
|
385
394
|
destructive "ln -s #{src} #{dst}" do
|
|
@@ -388,8 +397,6 @@ module Remote
|
|
|
388
397
|
end
|
|
389
398
|
end
|
|
390
399
|
|
|
391
|
-
#attr_accessor :impressionating_user
|
|
392
|
-
|
|
393
400
|
def spawn(cmd, expect_status: nil)
|
|
394
401
|
expect_status = [expect_status] unless expect_status.nil? || expect_status.respond_to?(:include?)
|
|
395
402
|
stdout_r, stdout_w = IO.pipe
|
|
@@ -510,4 +517,11 @@ module Remote
|
|
|
510
517
|
@verbose = true
|
|
511
518
|
end
|
|
512
519
|
end.parse!
|
|
520
|
+
|
|
521
|
+
@performed = false
|
|
522
|
+
def perform!
|
|
523
|
+
return if @performed
|
|
524
|
+
info "ok: #{ok_counter}, changed: #{changed_counter}"
|
|
525
|
+
@performed = true
|
|
526
|
+
end
|
|
513
527
|
end
|
data/remote/remote_dsl.rb
CHANGED
|
@@ -181,8 +181,12 @@ def remote_file(path)
|
|
|
181
181
|
Remote::RemoteFile.new(path)
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
-
def perform!
|
|
185
|
-
Remote.
|
|
184
|
+
def perform! # legacy, not needed since 0.2
|
|
185
|
+
Remote.perform!
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
Kernel.at_exit do
|
|
189
|
+
Remote.perform!
|
|
186
190
|
end
|
|
187
191
|
|
|
188
192
|
# Monkey-patching
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hatecf
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexander Markov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-03-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Configuration management engine like Ansible but without YAML and 30
|
|
14
14
|
times faster
|