evesync 1.0.2

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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +25 -0
  3. data/Rakefile +83 -0
  4. data/bin/evedatad +34 -0
  5. data/bin/evehand +36 -0
  6. data/bin/evemond +42 -0
  7. data/bin/evesync +164 -0
  8. data/bin/evesyncd +44 -0
  9. data/bin/start +16 -0
  10. data/config/example.conf +58 -0
  11. data/lib/evesync/config.rb +63 -0
  12. data/lib/evesync/constants.rb +17 -0
  13. data/lib/evesync/database.rb +107 -0
  14. data/lib/evesync/discover.rb +77 -0
  15. data/lib/evesync/err.rb +25 -0
  16. data/lib/evesync/handler/file.rb +28 -0
  17. data/lib/evesync/handler/package.rb +30 -0
  18. data/lib/evesync/handler.rb +89 -0
  19. data/lib/evesync/ipc/client.rb +37 -0
  20. data/lib/evesync/ipc/data/file.rb +64 -0
  21. data/lib/evesync/ipc/data/hashable.rb +74 -0
  22. data/lib/evesync/ipc/data/ignore.rb +22 -0
  23. data/lib/evesync/ipc/data/package.rb +58 -0
  24. data/lib/evesync/ipc/data/utils.rb +14 -0
  25. data/lib/evesync/ipc/data.rb +50 -0
  26. data/lib/evesync/ipc/ipc.rb +42 -0
  27. data/lib/evesync/ipc/server.rb +56 -0
  28. data/lib/evesync/log.rb +66 -0
  29. data/lib/evesync/ntp.rb +16 -0
  30. data/lib/evesync/os/linux/arch/package_manager.rb +29 -0
  31. data/lib/evesync/os/linux/arch/package_watcher.rb +59 -0
  32. data/lib/evesync/os/linux/arch.rb +2 -0
  33. data/lib/evesync/os/linux/base_package_manager.rb +80 -0
  34. data/lib/evesync/os/linux/deb/dpkg.rb +30 -0
  35. data/lib/evesync/os/linux/deb/package_manager.rb +38 -0
  36. data/lib/evesync/os/linux/deb/package_watcher.rb +32 -0
  37. data/lib/evesync/os/linux/deb.rb +2 -0
  38. data/lib/evesync/os/linux/rhel/package_manager.rb +42 -0
  39. data/lib/evesync/os/linux/rhel/package_watcher.rb +32 -0
  40. data/lib/evesync/os/linux/rhel/rpm.rb +41 -0
  41. data/lib/evesync/os/linux/rhel.rb +3 -0
  42. data/lib/evesync/os/linux.rb +9 -0
  43. data/lib/evesync/os.rb +2 -0
  44. data/lib/evesync/sync.rb +209 -0
  45. data/lib/evesync/trigger/base.rb +56 -0
  46. data/lib/evesync/trigger/file.rb +20 -0
  47. data/lib/evesync/trigger/package.rb +20 -0
  48. data/lib/evesync/trigger.rb +106 -0
  49. data/lib/evesync/utils.rb +51 -0
  50. data/lib/evesync/watcher/file.rb +156 -0
  51. data/lib/evesync/watcher/interface.rb +21 -0
  52. data/lib/evesync/watcher/package.rb +8 -0
  53. data/lib/evesync/watcher.rb +68 -0
  54. data/lib/evesync.rb +3 -0
  55. metadata +198 -0
@@ -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
@@ -0,0 +1,16 @@
1
+ require 'net/ntp'
2
+ require 'evesync/config'
3
+
4
+ module Evesync
5
+ module NTP
6
+
7
+ def self.time
8
+ Net::NTP.get(Config['ntp']).time
9
+ end
10
+
11
+ def self.timestamp
12
+ time.to_f.to_s
13
+ end
14
+
15
+ end
16
+ end
@@ -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,2 @@
1
+ require_relative './arch/package_watcher.rb'
2
+ require_relative './arch/package_manager.rb'
@@ -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,2 @@
1
+ require_relative './deb/package_watcher.rb'
2
+ require_relative './deb/package_manager.rb'
@@ -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
@@ -0,0 +1,3 @@
1
+ # TODO: add check if rpm exists
2
+ require_relative './rhel/package_watcher.rb'
3
+ require_relative './rhel/package_manager.rb'
@@ -0,0 +1,9 @@
1
+ text = File.new('/etc/os-release').read
2
+
3
+ if text =~ /^ID.*(rhel|centos|fedora)/
4
+ require 'evesync/os/linux/rhel'
5
+ elsif text =~ /ID.*arch/
6
+ require 'evesync/os/linux/arch'
7
+ elsif text =~ /ID.*debian/
8
+ require 'evesync/os/linux/deb'
9
+ end
data/lib/evesync/os.rb ADDED
@@ -0,0 +1,2 @@
1
+ # TODO: Fix to catch different OSes
2
+ require 'evesync/os/linux'