evesync 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +25 -0
- data/Rakefile +83 -0
- data/bin/evedatad +34 -0
- data/bin/evehand +36 -0
- data/bin/evemond +42 -0
- data/bin/evesync +164 -0
- data/bin/evesyncd +44 -0
- data/bin/start +16 -0
- data/config/example.conf +58 -0
- data/lib/evesync/config.rb +63 -0
- data/lib/evesync/constants.rb +17 -0
- data/lib/evesync/database.rb +107 -0
- data/lib/evesync/discover.rb +77 -0
- data/lib/evesync/err.rb +25 -0
- data/lib/evesync/handler/file.rb +28 -0
- data/lib/evesync/handler/package.rb +30 -0
- data/lib/evesync/handler.rb +89 -0
- data/lib/evesync/ipc/client.rb +37 -0
- data/lib/evesync/ipc/data/file.rb +64 -0
- data/lib/evesync/ipc/data/hashable.rb +74 -0
- data/lib/evesync/ipc/data/ignore.rb +22 -0
- data/lib/evesync/ipc/data/package.rb +58 -0
- data/lib/evesync/ipc/data/utils.rb +14 -0
- data/lib/evesync/ipc/data.rb +50 -0
- data/lib/evesync/ipc/ipc.rb +42 -0
- data/lib/evesync/ipc/server.rb +56 -0
- data/lib/evesync/log.rb +66 -0
- data/lib/evesync/ntp.rb +16 -0
- data/lib/evesync/os/linux/arch/package_manager.rb +29 -0
- data/lib/evesync/os/linux/arch/package_watcher.rb +59 -0
- data/lib/evesync/os/linux/arch.rb +2 -0
- data/lib/evesync/os/linux/base_package_manager.rb +80 -0
- data/lib/evesync/os/linux/deb/dpkg.rb +30 -0
- data/lib/evesync/os/linux/deb/package_manager.rb +38 -0
- data/lib/evesync/os/linux/deb/package_watcher.rb +32 -0
- data/lib/evesync/os/linux/deb.rb +2 -0
- data/lib/evesync/os/linux/rhel/package_manager.rb +42 -0
- data/lib/evesync/os/linux/rhel/package_watcher.rb +32 -0
- data/lib/evesync/os/linux/rhel/rpm.rb +41 -0
- data/lib/evesync/os/linux/rhel.rb +3 -0
- data/lib/evesync/os/linux.rb +9 -0
- data/lib/evesync/os.rb +2 -0
- data/lib/evesync/sync.rb +209 -0
- data/lib/evesync/trigger/base.rb +56 -0
- data/lib/evesync/trigger/file.rb +20 -0
- data/lib/evesync/trigger/package.rb +20 -0
- data/lib/evesync/trigger.rb +106 -0
- data/lib/evesync/utils.rb +51 -0
- data/lib/evesync/watcher/file.rb +156 -0
- data/lib/evesync/watcher/interface.rb +21 -0
- data/lib/evesync/watcher/package.rb +8 -0
- data/lib/evesync/watcher.rb +68 -0
- data/lib/evesync.rb +3 -0
- metadata +198 -0
data/lib/evesync/log.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'evesync/config'
|
3
|
+
require 'evesync/constants'
|
4
|
+
|
5
|
+
# This module is responsible for logging
|
6
|
+
module Evesync
|
7
|
+
module Log
|
8
|
+
# Supported levels for logging
|
9
|
+
LEVELS = %i[debug info warn error fatal].freeze
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def method_missing(m, *args)
|
13
|
+
# Unlisted methods are not allowed
|
14
|
+
raise NoMethodError unless LEVELS.include?(m)
|
15
|
+
|
16
|
+
check_logger
|
17
|
+
@logger.send(m, to_string(*args))
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def check_logger
|
22
|
+
init_logger unless @logger
|
23
|
+
end
|
24
|
+
|
25
|
+
def level=(lvl)
|
26
|
+
check_logger
|
27
|
+
if lvl.is_a?(Symbol) or lvl.is_a?(String)
|
28
|
+
@logger.level =
|
29
|
+
begin
|
30
|
+
Logger.const_get(lvl.to_s.upcase)
|
31
|
+
rescue NameError
|
32
|
+
Logger::DEBUG
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def level
|
38
|
+
check_logger
|
39
|
+
@logger.level
|
40
|
+
end
|
41
|
+
|
42
|
+
def simple=(bool)
|
43
|
+
init_logger unless @logger
|
44
|
+
if bool
|
45
|
+
@logger.formatter = proc do |_sev, _dt, _prog, msg|
|
46
|
+
"#{msg}\n"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def init_logger
|
52
|
+
@logger = Logger.new(STDERR)
|
53
|
+
@logger.formatter = proc do |sev, dtime, _prog, msg|
|
54
|
+
time = dtime.strftime('%Y-%m-%d %H:%M:%S')
|
55
|
+
prog = File.basename($PROGRAM_NAME)
|
56
|
+
"[#{time}] #{prog.ljust(8)} #{sev.ljust(5)}: #{msg}\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_string(*args)
|
61
|
+
to_s_with_space = ->(s) { "#{s} " }
|
62
|
+
args.map(&to_s_with_space).reduce(&:+).strip
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/evesync/ntp.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Evesync
|
2
|
+
module OS
|
3
|
+
# FIXME: pacman downgrading requires full url path
|
4
|
+
module PackageManager
|
5
|
+
class << self
|
6
|
+
def install(*args)
|
7
|
+
pacman('-Sy', *args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def remove(*args)
|
11
|
+
pacman('-R', *args)
|
12
|
+
end
|
13
|
+
|
14
|
+
# FIXME: update and downgrade specific version is not fine
|
15
|
+
def update(*args)
|
16
|
+
pacman('-U', *args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def downgrade(*args)
|
20
|
+
pacman('-U', *args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def pacman(cmd, name, _version)
|
24
|
+
`pacman #{cmd} #{name}` # FIXME: do smth with version
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'file-tail'
|
2
|
+
require 'evesync/log'
|
3
|
+
require 'evesync/config'
|
4
|
+
require 'evesync/ipc/data/package'
|
5
|
+
require 'evesync/watcher/interface'
|
6
|
+
|
7
|
+
module Evesync
|
8
|
+
module OS
|
9
|
+
|
10
|
+
# Watcher for package changes for Arch Linux
|
11
|
+
#
|
12
|
+
# = Example
|
13
|
+
# Thread.new { IPC::Data::PackageWatcher.new(queue).run }
|
14
|
+
class PackageWatcher < Watcher::Interface
|
15
|
+
ARCH_LOG_FILE = '/var/log/pacman.log'.freeze
|
16
|
+
PKG_REGEXP =
|
17
|
+
/(?<command>reinstalled|installed|removed)
|
18
|
+
\s*
|
19
|
+
(?<package>\w+)
|
20
|
+
\s*
|
21
|
+
\( (?<version>[\w\d.-]+) \)
|
22
|
+
/x.freeze
|
23
|
+
|
24
|
+
private_constant :ARCH_LOG_FILE, :PKG_REGEXP
|
25
|
+
|
26
|
+
def initialize(queue)
|
27
|
+
@queue = queue
|
28
|
+
Log.debug('Arch Package watcher initialized')
|
29
|
+
end
|
30
|
+
|
31
|
+
def start
|
32
|
+
Log.debug('Arch Package watcher started')
|
33
|
+
@thr = Thread.new do
|
34
|
+
File.open(ARCH_LOG_FILE) do |log|
|
35
|
+
log.extend(File::Tail)
|
36
|
+
log.interval = Config[:evemond]['watch-interval']
|
37
|
+
log.backward(1)
|
38
|
+
log.tail do |line|
|
39
|
+
m = line.match(PKG_REGEXP)
|
40
|
+
next unless m
|
41
|
+
|
42
|
+
pkg = IPC::Data::Package.new(
|
43
|
+
name: m[:package],
|
44
|
+
version: m[:version],
|
45
|
+
command: m[:command]
|
46
|
+
)
|
47
|
+
@queue << pkg
|
48
|
+
Log.debug 'Arch package watcher enqued:', pkg
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def stop
|
55
|
+
@thr.exit
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'hashdiff'
|
2
|
+
require 'evesync/ipc/data/package'
|
3
|
+
|
4
|
+
module Evesync
|
5
|
+
module OS
|
6
|
+
module BasePackageManager
|
7
|
+
def initialize
|
8
|
+
@packages = make_pkg_snapshot
|
9
|
+
end
|
10
|
+
|
11
|
+
def changes
|
12
|
+
# make hash of all packages
|
13
|
+
snapshot = make_pkg_snapshot
|
14
|
+
# diff with last version
|
15
|
+
diff = HashDiff.diff(@packages, snapshot)
|
16
|
+
# parse changes into IPC::Data::Package array
|
17
|
+
packages = parse_pkg_diff(diff)
|
18
|
+
# use new hash as default
|
19
|
+
# FIXME: wait if the changes were saved
|
20
|
+
# and properly handled
|
21
|
+
@packages = snapshot
|
22
|
+
packages
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Parses changes, given by 'hashdiff' gem into
|
28
|
+
# IPC::Data::Package array
|
29
|
+
def parse_pkg_diff(diffs)
|
30
|
+
packages = []
|
31
|
+
diffs.each do |diff|
|
32
|
+
package = case diff[0]
|
33
|
+
when '-' then removed_package(diff)
|
34
|
+
when '+' then installed_package(diff)
|
35
|
+
when '~' then updated_package(diff)
|
36
|
+
end
|
37
|
+
packages.push(package)
|
38
|
+
end
|
39
|
+
|
40
|
+
packages
|
41
|
+
end
|
42
|
+
|
43
|
+
def removed_package(diff)
|
44
|
+
IPC::Data::Package.new(
|
45
|
+
name: diff[1],
|
46
|
+
version: diff[2],
|
47
|
+
command: IPC::Data::Package::Command::REMOVE
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
def installed_package(diff)
|
52
|
+
IPC::Data::Package.new(
|
53
|
+
name: diff[1],
|
54
|
+
version: diff[2],
|
55
|
+
command: IPC::Data::Package::Command::INSTALL
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def updated_package(diff)
|
60
|
+
command = if pkg_version_less(diff[2], diff[3])
|
61
|
+
IPC::Data::Package::Command::UPDATE
|
62
|
+
else
|
63
|
+
IPC::Data::Package::Command::DOWNGRADE
|
64
|
+
end
|
65
|
+
|
66
|
+
IPC::Data::Package.new(
|
67
|
+
name: diff[1],
|
68
|
+
version: diff[3],
|
69
|
+
command: command
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
# FIXME:
|
74
|
+
# - research about restrictions and make sure this work
|
75
|
+
def pkg_version_less(a, b)
|
76
|
+
a < b
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'hashdiff'
|
2
|
+
require 'evesync/log'
|
3
|
+
require 'evesync/os/linux/base_package_manager'
|
4
|
+
|
5
|
+
module Evesync
|
6
|
+
module OS
|
7
|
+
class Dpkg
|
8
|
+
include BasePackageManager
|
9
|
+
|
10
|
+
PKG_QUERY = 'dpkg-query -l'.freeze
|
11
|
+
|
12
|
+
private_constant :PKG_QUERY
|
13
|
+
|
14
|
+
# Snapshot is a hash where key is a package name
|
15
|
+
# and value - it's version.
|
16
|
+
# This function returns a snapshot of a system
|
17
|
+
# package status for a moment
|
18
|
+
def make_pkg_snapshot
|
19
|
+
snapshot = {}
|
20
|
+
query_output = `#{PKG_QUERY}`
|
21
|
+
query_output.lines.each do |line|
|
22
|
+
info = line.split
|
23
|
+
snapshot[info[1]] = info[2]
|
24
|
+
end
|
25
|
+
|
26
|
+
snapshot
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Evesync
|
2
|
+
module OS
|
3
|
+
module PackageManager
|
4
|
+
class << self
|
5
|
+
def install(*args)
|
6
|
+
apt_get('install', *args)
|
7
|
+
exist?(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def remove(*args)
|
11
|
+
apt_get('remove', *args)
|
12
|
+
!exist?(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def update(*args)
|
16
|
+
apt_get('upgrade', *args)
|
17
|
+
exist?(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def downgrade(*args)
|
21
|
+
apt_get('install', *args)
|
22
|
+
exist?(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def apt_get(cmd, name, version)
|
26
|
+
Log.debug("Apt-get command: '#{cmd}' on #{name}=#{version}")
|
27
|
+
system("apt-get --assume-yes #{cmd} #{name}=#{version}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def exist?(name, version)
|
31
|
+
Log.debug("Dpkg checking if exists: #{name}-#{version}")
|
32
|
+
`dpkg-query -l #{name}`
|
33
|
+
$CHILD_STATUS == 0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'evesync/log'
|
2
|
+
require 'evesync/watcher/interface'
|
3
|
+
require_relative './dpkg'
|
4
|
+
|
5
|
+
module Evesync
|
6
|
+
module OS
|
7
|
+
class PackageWatcher < Watcher::Interface
|
8
|
+
def initialize(queue)
|
9
|
+
@queue = queue
|
10
|
+
@dpkg = Dpkg.new
|
11
|
+
Log.debug('Debian Package watcher initialized')
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
Log.debug('Debian Package watcher started')
|
16
|
+
@thr = Thread.new do
|
17
|
+
loop do
|
18
|
+
sleep 10
|
19
|
+
@dpkg.changes.each do |pkg|
|
20
|
+
@queue << pkg
|
21
|
+
Log.debug 'Debian Package watcher enqued:', pkg
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def stop
|
28
|
+
@thr.exit
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'evesync/log'
|
2
|
+
|
3
|
+
# Manages package manager things
|
4
|
+
# TODO: trigger package_watcher event to update database
|
5
|
+
module Evesync
|
6
|
+
module OS
|
7
|
+
module PackageManager
|
8
|
+
class << self
|
9
|
+
def install(*args)
|
10
|
+
return false if exist?(*args)
|
11
|
+
yum('install', *args)
|
12
|
+
exist?(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove(*args)
|
16
|
+
yum('remove', *args)
|
17
|
+
!exist?(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def update(*args)
|
21
|
+
yum('update', *args)
|
22
|
+
exist?(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def downgrade(*args)
|
26
|
+
yum('downgrade', *args)
|
27
|
+
exist?(*args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def yum(cmd, name, version)
|
31
|
+
Log.debug("Yum command: '#{cmd}' on #{name}-#{version}")
|
32
|
+
system("yum --assumeyes #{cmd} #{name}-#{version}")
|
33
|
+
end
|
34
|
+
|
35
|
+
def exist?(name, version)
|
36
|
+
Log.debug("Yum checking if exists: #{name}-#{version}")
|
37
|
+
system("rpm -q #{name}-#{version} >/dev/null 2>&1")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative './rpm'
|
2
|
+
require 'evesync/log'
|
3
|
+
require 'evesync/watcher/interface'
|
4
|
+
|
5
|
+
module Evesync
|
6
|
+
module OS
|
7
|
+
class PackageWatcher < Watcher::Interface
|
8
|
+
def initialize(queue)
|
9
|
+
@queue = queue
|
10
|
+
@rpm_packages = Rpm.new
|
11
|
+
Log.debug('Rhel Package watcher initialized')
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
Log.debug('Rhel Package watcher started')
|
16
|
+
@thr = Thread.new do
|
17
|
+
loop do
|
18
|
+
sleep 10 # FIXME: don't use magic numbers
|
19
|
+
@rpm_packages.changes.each do |pkg|
|
20
|
+
@queue << pkg
|
21
|
+
Log.debug 'Rhel Package watcher enqued:', pkg
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def stop
|
28
|
+
@thr.exit
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'evesync/log'
|
2
|
+
require 'evesync/os/linux/base_package_manager'
|
3
|
+
|
4
|
+
module Evesync
|
5
|
+
module OS
|
6
|
+
|
7
|
+
# Rpm packages changes watcher. Yum history makes it
|
8
|
+
# difficult to handler package removals. So, rpm is
|
9
|
+
# the only tool that show all packages in the system.
|
10
|
+
# This class handles packages changes.
|
11
|
+
#
|
12
|
+
# = Example:
|
13
|
+
# rpm = Evesync::Rpm.new
|
14
|
+
# sleep 1000
|
15
|
+
# rpm.changed.each do |package|
|
16
|
+
# p package # print packages that changed
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# = TODO:
|
20
|
+
# * add reinstall handling also
|
21
|
+
#
|
22
|
+
class Rpm
|
23
|
+
include BasePackageManager
|
24
|
+
# Query for rpm list
|
25
|
+
PKG_QUERY = 'rpm -qa --queryformat "%{NAME} %{VERSION}-%{RELEASE}.%{ARCH}\n"'.freeze
|
26
|
+
|
27
|
+
private_constant :PKG_QUERY
|
28
|
+
|
29
|
+
def make_pkg_snapshot
|
30
|
+
snapshot = {}
|
31
|
+
query_output = `#{PKG_QUERY}`
|
32
|
+
query_output.lines.each do |line|
|
33
|
+
info = line.split
|
34
|
+
snapshot[info[0]] = info[1]
|
35
|
+
end
|
36
|
+
|
37
|
+
snapshot
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/evesync/os.rb
ADDED