2026-05-03 00:54:14 +03:00
|
|
|
#!/opt/brepo/ruby33/bin/ruby
|
|
|
|
|
|
|
|
|
|
require 'pathname'
|
|
|
|
|
require 'fileutils'
|
2026-05-03 16:32:53 +03:00
|
|
|
require 'digest'
|
2026-05-03 00:54:14 +03:00
|
|
|
|
|
|
|
|
class UpdateWorker < Kernel::ModuleCoreWorker
|
|
|
|
|
MODULE_ID = "update_module"
|
|
|
|
|
|
|
|
|
|
def info
|
|
|
|
|
{
|
|
|
|
|
ID: 6,
|
|
|
|
|
NAME: MODULE_ID,
|
|
|
|
|
DESCR: "Module for updating HestiaCP data and templates",
|
|
|
|
|
REQ: "",
|
|
|
|
|
CONF: "yes",
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def file_changed?(new_file, old_file)
|
|
|
|
|
return true unless File.exist?(old_file)
|
|
|
|
|
new_hash = Digest::SHA256.file(new_file).hexdigest
|
|
|
|
|
old_hash = Digest::SHA256.file(old_file).hexdigest
|
|
|
|
|
new_hash != old_hash
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def get_templates_map()
|
|
|
|
|
{ :templates=>
|
|
|
|
|
[
|
|
|
|
|
{:new=>"/usr/local/hestia/install/rpm/templates/web/awstats", :old=>"/usr/local/hestia/data/templates/web/awstats"},
|
|
|
|
|
{:new=>"/usr/local/hestia/install/rpm/templates/web/httpd", :old=>"/usr/local/hestia/data/templates/web/httpd"},
|
|
|
|
|
{:new=>"/usr/local/hestia/install/rpm/templates/web/nginx", :old=>"/usr/local/hestia/data/templates/web/nginx"},
|
|
|
|
|
{:new=>"/usr/local/hestia/install/rpm/templates/web/php-fpm", :old=>"/usr/local/hestia/data/templates/web/php-fpm"}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
# New helper method to get list of changed template files
|
|
|
|
|
def get_changed_template_files
|
|
|
|
|
templates_map = get_templates_map()[:templates]
|
|
|
|
|
result = []
|
|
|
|
|
templates_map.each do |tpl|
|
|
|
|
|
new_dir = tpl[:new]
|
|
|
|
|
old_dir = tpl[:old]
|
|
|
|
|
Dir.glob(File.join(new_dir, '**', '*')).each do |new_file|
|
|
|
|
|
next if File.directory?(new_file)
|
|
|
|
|
rel_path = Pathname.new(new_file).relative_path_from(Pathname.new(new_dir)).to_s
|
|
|
|
|
old_file = File.join(old_dir, rel_path)
|
|
|
|
|
result << [new_dir, new_file, old_file] if file_changed?(new_file, old_file)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
result
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def command(args)
|
|
|
|
|
return log_return("Not enough arguments. Needed command") if args.length < 1
|
|
|
|
|
log_file = get_log
|
|
|
|
|
|
|
|
|
|
m_command = args[0].strip
|
|
|
|
|
case m_command
|
|
|
|
|
when "synctemplates"
|
|
|
|
|
result = get_changed_template_files
|
|
|
|
|
result.each do |new_dir, new_file, old_file|
|
|
|
|
|
if !File.exist?(old_file)
|
|
|
|
|
FileUtils.cp(new_file, old_file)
|
|
|
|
|
else
|
|
|
|
|
stat = File.stat(old_file)
|
|
|
|
|
uid = stat.uid
|
|
|
|
|
gid = stat.gid
|
|
|
|
|
mode = stat.mode & 0o7777
|
|
|
|
|
FileUtils.cp(new_file, old_file)
|
|
|
|
|
File.chown(uid, gid, old_file)
|
|
|
|
|
File.chmod(mode, old_file)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
ACTION_OK
|
|
|
|
|
when "listsynctemplates"
|
|
|
|
|
format = (args[1].nil? ? "shell" : args[1].strip)
|
|
|
|
|
list = get_changed_template_files
|
|
|
|
|
result = []
|
|
|
|
|
result = list.map do |new_dir, new_file, old_file|
|
|
|
|
|
file_name = Pathname.new(new_file).relative_path_from(Pathname.new(new_dir)).to_s
|
2026-05-03 16:32:53 +03:00
|
|
|
dir_name = File.basename(new_dir)
|
|
|
|
|
relative_path = Pathname.new(new_file).relative_path_from(Pathname.new(new_dir)).to_s
|
|
|
|
|
file_name = File.join(dir_name, relative_path)
|
2026-05-03 00:54:14 +03:00
|
|
|
{
|
|
|
|
|
"FILE_NAME" => file_name,
|
|
|
|
|
"NEW_SIZE" => File.size(new_file),
|
|
|
|
|
"OLD_SIZE" => File.exist?(old_file) ? File.size(old_file) : "-"
|
|
|
|
|
}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
hestia_print_array_of_hashes(result, format, "FILE_NAME,NEW_SIZE,OLD_SIZE")
|
|
|
|
|
ACTION_OK
|
|
|
|
|
when "help"
|
|
|
|
|
puts "#{$0} update_module COMMAND [json|csv|plain]"
|
|
|
|
|
puts "COMMANDS:"
|
|
|
|
|
puts " synctemplates - sync web templates"
|
|
|
|
|
puts " listsynctemplates - show changed web templates"
|
|
|
|
|
puts " help - help"
|
|
|
|
|
ACTION_OK
|
|
|
|
|
else
|
|
|
|
|
log_return("Unknown command. #{args}")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
implements IPluginInterface
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
module UpdateModule
|
|
|
|
|
def get_object
|
|
|
|
|
Proc.new { UpdateWorker.new }
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
module_function :get_object
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
class Kernel::PluginConfiguration
|
|
|
|
|
include UpdateModule
|
|
|
|
|
|
|
|
|
|
@@loaded_plugins[UpdateWorker::MODULE_ID] = UpdateModule.get_object
|
|
|
|
|
end
|