triglav-agent 1.0.0.pre1

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 (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/.yardopts +6 -0
  6. data/CHANGELOG.md +3 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +5 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +59 -0
  11. data/Rakefile +11 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/docs/Triglav/Agent/ApiClient/AuthenticationError.html +150 -0
  15. data/docs/Triglav/Agent/ApiClient/ConnectionError.html +150 -0
  16. data/docs/Triglav/Agent/ApiClient/Error.html +296 -0
  17. data/docs/Triglav/Agent/ApiClient.html +545 -0
  18. data/docs/Triglav/Agent/Base/CLI.html +498 -0
  19. data/docs/Triglav/Agent/Base/Connection.html +258 -0
  20. data/docs/Triglav/Agent/Base/Monitor.html +370 -0
  21. data/docs/Triglav/Agent/Base/Processor.html +623 -0
  22. data/docs/Triglav/Agent/Base/Setting.html +1081 -0
  23. data/docs/Triglav/Agent/Base/Worker.html +635 -0
  24. data/docs/Triglav/Agent/Base.html +121 -0
  25. data/docs/Triglav/Agent/Configuration.html +967 -0
  26. data/docs/Triglav/Agent/Error.html +130 -0
  27. data/docs/Triglav/Agent/HashUtil.html +351 -0
  28. data/docs/Triglav/Agent/LogFormatter.html +271 -0
  29. data/docs/Triglav/Agent/Logger.html +287 -0
  30. data/docs/Triglav/Agent/StorageFile.html +1130 -0
  31. data/docs/Triglav/Agent/Timer.html +424 -0
  32. data/docs/Triglav/Agent/TooManyError.html +134 -0
  33. data/docs/Triglav/Agent.html +131 -0
  34. data/docs/Triglav.html +119 -0
  35. data/docs/_index.html +335 -0
  36. data/docs/class_list.html +51 -0
  37. data/docs/css/common.css +1 -0
  38. data/docs/css/full_list.css +58 -0
  39. data/docs/css/style.css +481 -0
  40. data/docs/file.LICENSE.html +72 -0
  41. data/docs/file.README.html +137 -0
  42. data/docs/file_list.html +61 -0
  43. data/docs/frames.html +17 -0
  44. data/docs/index.html +137 -0
  45. data/docs/js/app.js +243 -0
  46. data/docs/js/full_list.js +216 -0
  47. data/docs/js/jquery.js +4 -0
  48. data/docs/method_list.html +659 -0
  49. data/docs/top-level-namespace.html +112 -0
  50. data/example/config.yml +40 -0
  51. data/lib/triglav/agent/api_client.rb +199 -0
  52. data/lib/triglav/agent/base/cli.rb +98 -0
  53. data/lib/triglav/agent/base/connection.rb +30 -0
  54. data/lib/triglav/agent/base/monitor.rb +32 -0
  55. data/lib/triglav/agent/base/processor.rb +136 -0
  56. data/lib/triglav/agent/base/setting.rb +112 -0
  57. data/lib/triglav/agent/base/worker.rb +95 -0
  58. data/lib/triglav/agent/configuration.rb +79 -0
  59. data/lib/triglav/agent/error.rb +4 -0
  60. data/lib/triglav/agent/hash_util.rb +36 -0
  61. data/lib/triglav/agent/logger.rb +50 -0
  62. data/lib/triglav/agent/storage_file.rb +144 -0
  63. data/lib/triglav/agent/timer.rb +80 -0
  64. data/lib/triglav/agent/version.rb +5 -0
  65. data/lib/triglav/agent.rb +20 -0
  66. data/lib/triglav-agent.rb +1 -0
  67. data/triglav-agent.gemspec +33 -0
  68. metadata +250 -0
@@ -0,0 +1,112 @@
1
+ require 'triglav/agent/hash_util'
2
+ require 'triglav/agent/logger'
3
+ require 'yaml'
4
+ require 'erb'
5
+
6
+ module Triglav::Agent
7
+ module Base
8
+ # A base class represents settings coming from config.yml and cli options
9
+ #
10
+ # This base class usually should be enough for agent plugins, but
11
+ # you can override this class and configure with Configuration#setting_class=
12
+ class Setting
13
+ attr_reader :cli_options
14
+
15
+ DEFAULT_LOG = 'STDOUT'.freeze
16
+ DEFAULT_LOG_LEVEL = 'info'.freeze
17
+ DEFAULT_APP_ENV = 'development'.freeze
18
+
19
+ def initialize(cli_options = {})
20
+ @cli_options = cli_options
21
+ if dotenv?
22
+ require 'dotenv'
23
+ Dotenv.load
24
+ end
25
+ end
26
+
27
+ def reload
28
+ Dotenv.overload if dotenv?
29
+ @config = nil
30
+ @logger.close rescue nil
31
+ @logger = nil
32
+ end
33
+
34
+ def app_env
35
+ @app_env ||= ENV['APP_ENV'] || DEFAULT_APP_ENV
36
+ end
37
+
38
+ def config_file
39
+ @cli_options[:config]
40
+ end
41
+
42
+ def status_file
43
+ @status_file ||= @cli_options[:status] || config.dig(:triglav, :status_file) || 'status.yml'
44
+ end
45
+
46
+ def token_file
47
+ @token_file ||= @cli_options[:token] || config.dig(:triglav, :token_file) || 'token.yml'
48
+ end
49
+
50
+ def dotenv?
51
+ @cli_options[:dotenv]
52
+ end
53
+
54
+ def debug?
55
+ @cli_options[:debug]
56
+ end
57
+
58
+ def logger
59
+ @logger ||= Logger.new(log, serverengine_logger_options)
60
+ end
61
+
62
+ def log_level
63
+ @cli_options[:log_level] || config.dig(:serverengine, :log_level) || DEFAULT_LOG_LEVEL
64
+ end
65
+
66
+ def log
67
+ @cli_options[:log] || config.dig(:serverengine, :log) || DEFAULT_LOG
68
+ end
69
+
70
+ def serverengine_options
71
+ serverengine_options = config[:serverengine].dup || {}
72
+ # serverengine_options[:workers] = 1 # default
73
+ # serverengine_options[:worker_type] = 'embedded' # default
74
+ serverengine_options.keys.each do |k|
75
+ serverengine_options.delete(k) if k.to_s.start_with?('log')
76
+ end
77
+ serverengine_options.merge!({
78
+ logger: logger,
79
+ log_level: log_level,
80
+ setting: self,
81
+ })
82
+ end
83
+
84
+ def [](key)
85
+ config[key]
86
+ end
87
+
88
+ def dig(*args)
89
+ config.dig(*args)
90
+ end
91
+
92
+ private
93
+
94
+ def config
95
+ @config ||=
96
+ begin
97
+ raw = File.read(config_file)
98
+ erb = ERB.new(raw, nil, "-").tap {|_| _.filename = config_file }
99
+ all = HashUtil.deep_symbolize_keys(YAML.load(erb.result(binding)))
100
+ all[app_env.to_sym]
101
+ end
102
+ end
103
+
104
+ def serverengine_logger_options
105
+ {
106
+ log: log,
107
+ log_level: log_level,
108
+ }
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,95 @@
1
+ require 'triglav/agent/timer'
2
+
3
+ module Triglav::Agent
4
+ module Base
5
+ # Triglav agent worker module for Serverengine.
6
+ #
7
+ # You usually do not need to customize this module, but if you want to
8
+ # implement your original, configure
9
+ #
10
+ # Triglav::Agent::Configuration.worker_module
11
+ module Worker
12
+ # serverengine interface
13
+ def initialize
14
+ @timer = Timer.new
15
+ end
16
+
17
+ # serverengine interface
18
+ def reload
19
+ $logger.info { "Worker#reload worker_id:#{worker_id}" }
20
+ $setting.reload
21
+ end
22
+
23
+ # serverengine interface
24
+ def run
25
+ $logger.info { "Worker#run worker_id:#{worker_id}" }
26
+ start
27
+ until @stop
28
+ @timer.wait(monitor_interval) { process }
29
+ end
30
+ rescue => e
31
+ # ServerEngine.dump_uncaught_error does not tell me e.class
32
+ log_error(e)
33
+ raise e
34
+ end
35
+
36
+ def process
37
+ started = Time.now
38
+ $logger.info { "Start Worker#process worker_id:#{worker_id}" }
39
+
40
+ total_count = 0
41
+ total_success_count = 0
42
+ resource_uri_prefixes.each do |resource_uri_prefix|
43
+ break if stopped?
44
+ processor = processor_class.new(self, resource_uri_prefix)
45
+ total_count += processor.total_count
46
+ total_success_count += processor.process
47
+ end
48
+
49
+ elapsed = Time.now - started
50
+ $logger.info {
51
+ "Finish Worker#process worker_id:#{worker_id} " \
52
+ "success_count/total_count:#{total_success_count}/#{total_count} elapsed:#{elapsed.to_f}sec"
53
+ }
54
+ end
55
+
56
+ def start
57
+ @timer.start
58
+ @stop = false
59
+ end
60
+
61
+ # serverengine interface
62
+ def stop
63
+ $logger.info { "Worker#stop worker_id:#{worker_id}" }
64
+ @stop = true
65
+ @timer.stop
66
+ end
67
+
68
+ def stopped?
69
+ @stop
70
+ end
71
+
72
+ private
73
+
74
+ def processor_class
75
+ Configuration.processor_class
76
+ end
77
+
78
+ def name
79
+ Configuration.name
80
+ end
81
+
82
+ def log_error(e)
83
+ $logger.error { "#{e.class} #{e.message} #{e.backtrace.join("\\n")}" } # one line
84
+ end
85
+
86
+ def monitor_interval
87
+ $setting.dig(name, :monitor_interval) || 60
88
+ end
89
+
90
+ def resource_uri_prefixes
91
+ $setting.dig(name, :connection_info).keys
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,79 @@
1
+ module Triglav
2
+ module Agent
3
+ # Configure Triglav::Agent framework
4
+ #
5
+ # require 'triglav/agent/configuration'
6
+ # require 'triglav/agent/vertica/worker'
7
+ # Triglav::Agent::Configuration.configure do |config|
8
+ # config.name = :vertica # default: :agent
9
+ # config.cli_class = Triglav::Agent::Vertica::CLI
10
+ # config.setting_class = Triglav::Agent::Vertica::Setting
11
+ # config.worker_module = Triglav::Agent::Vertica::Worker
12
+ # config.processor_class = Triglav::Agent::Vertica::Processor
13
+ # config.monitor_class = Triglav::Agent::Vertica::Monitor
14
+ # config.connection_class = Triglav::Agent::Vertica::Connection
15
+ # end
16
+ # Triglav::Agent::Configuration.cli_class.new.run
17
+ class Configuration
18
+ def self.configure(&block)
19
+ yield(Triglav::Agent::Configuration)
20
+ end
21
+
22
+ def self.worker_module
23
+ @worker_module ||= Triglav::Agent::Base::Worker
24
+ end
25
+
26
+ def self.processor_class
27
+ @processor_class ||= Triglav::Agent::Base::Processor
28
+ end
29
+
30
+ def self.monitor_class
31
+ @monitor_class ||= Triglav::Agent::Base::Monitor
32
+ end
33
+
34
+ def self.connection_class
35
+ @connection_class ||= Triglav::Agent::Base::Connection
36
+ end
37
+
38
+ def self.setting_class
39
+ @setting_class ||= Triglav::Agent::Base::Setting
40
+ end
41
+
42
+ def self.cli_class
43
+ @cli_class ||= Triglav::Agent::Base::CLI
44
+ end
45
+
46
+ def self.name
47
+ @name ||= :agent
48
+ end
49
+
50
+ def self.worker_module=(worker_module)
51
+ @worker_module = worker_module
52
+ end
53
+
54
+ def self.processor_class=(processor_class)
55
+ @processor_class = processor_class
56
+ end
57
+
58
+ def self.monitor_class=(monitor_class)
59
+ @monitor_class = monitor_class
60
+ end
61
+
62
+ def self.connection_class=(connection_class)
63
+ @connection_class = connection_class
64
+ end
65
+
66
+ def self.setting_class=(setting_class)
67
+ @setting_class = setting_class
68
+ end
69
+
70
+ def self.cli_class=(cli_class)
71
+ @cli_class = cli_class
72
+ end
73
+
74
+ def self.name=(name)
75
+ @name = name
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,4 @@
1
+ module Triglav::Agent
2
+ class Error < ::StandardError; end
3
+ class TooManyError < Error; end
4
+ end
@@ -0,0 +1,36 @@
1
+ module Triglav::Agent
2
+ class HashUtil
3
+ def self.deep_symbolize_keys(obj)
4
+ case obj
5
+ when Hash
6
+ obj.map {|k, v| [k.to_sym, deep_symbolize_keys(v)] }.to_h
7
+ when Array
8
+ obj.map {|v| deep_symbolize_keys(v) }
9
+ else
10
+ obj
11
+ end
12
+ end
13
+
14
+ def self.deep_stringify_keys(obj)
15
+ case obj
16
+ when Hash
17
+ obj.map {|k, v| [k.to_s, deep_stringify_keys(v)] }.to_h
18
+ when Array
19
+ obj.map {|v| deep_stringify_keys(v) }
20
+ else
21
+ obj
22
+ end
23
+ end
24
+
25
+ # HashUtil.setdig(hash, ['a', 'b'], 'bar') # like hash['a']['b'] = 'bar'
26
+ def self.setdig(hash, key, val)
27
+ keys = Array(key)
28
+ sub_hash = hash
29
+ keys[0...-1].each do |k|
30
+ sub_hash = (sub_hash[k] ||= {})
31
+ end
32
+ sub_hash[keys.last] = val
33
+ hash
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,50 @@
1
+ require 'serverengine/daemon_logger'
2
+
3
+ module Triglav::Agent
4
+ # Logger class
5
+ #
6
+ # require 'triglav/agent/logger'
7
+ # logger = Logger.new('STDOUT', opts = {})
8
+ class Logger < ::ServerEngine::DaemonLogger
9
+ def initialize(logdev, *args)
10
+ logdev = STDOUT if logdev == 'STDOUT'
11
+ logdev = STDERR if logdev == 'STDERR'
12
+ super(logdev, *args)
13
+ @formatter = LogFormatter.new
14
+ end
15
+
16
+ def write(msg)
17
+ @logdev.write msg
18
+ end
19
+ end
20
+
21
+ class LogFormatter
22
+ FORMAT = "%s [%s] %s %s\n"
23
+
24
+ def initialize(opts={})
25
+ end
26
+
27
+ def call(severity, time, progname, msg)
28
+ FORMAT % [format_datetime(time), severity, format_pid, format_message(msg)]
29
+ end
30
+
31
+ private
32
+ def format_datetime(time)
33
+ time.strftime("%Y-%m-%dT%H:%M:%S.%6N%:z")
34
+ end
35
+
36
+ def format_pid
37
+ "PID-#{::Process.pid} TID-#{Thread.current.object_id}"
38
+ end
39
+
40
+ def format_message(message)
41
+ case message
42
+ when ::Exception
43
+ e = message
44
+ "#{e.class} (#{e.message})\\n #{e.backtrace.join("\\n ")}"
45
+ else
46
+ message.to_s.gsub(/\n/, "\\n")
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,144 @@
1
+ require 'triglav/agent/hash_util'
2
+ require 'yaml'
3
+
4
+ module Triglav::Agent
5
+ # Thread and inter-process safe YAML file storage
6
+ #
7
+ # StorageFile.open($setting.status_file) do |fp|
8
+ # status = fp.load
9
+ # status['foo'] = 'bar'
10
+ # fp.dump(status)
11
+ # end
12
+ class StorageFile
13
+ attr_reader :fp
14
+
15
+ private def initialize(fp)
16
+ @fp = fp
17
+ end
18
+
19
+ # Load storage file
20
+ #
21
+ # StorageFile.load($setting.status_file)
22
+ #
23
+ # @param [String] path
24
+ # @return [Hash]
25
+ def self.load(path)
26
+ open(path) {|fp| fp.load }
27
+ end
28
+
29
+ # Open storage file
30
+ #
31
+ # StorageFile.open($setting.status_file) do |fp|
32
+ # status = fp.load
33
+ # status['foo'] = 'bar'
34
+ # fp.dump(status)
35
+ # end
36
+ #
37
+ # @param [String] path
38
+ # @param [Block] block
39
+ def self.open(path, &block)
40
+ fp = File.open(path, (File::RDONLY | File::CREAT))
41
+ until fp.flock(File::LOCK_EX | File::LOCK_NB)
42
+ $logger.info { "Somebody else is locking the storage file #{path.inspect}" }
43
+ sleep 0.5
44
+ end
45
+ begin
46
+ return yield(StorageFile.new(fp))
47
+ ensure
48
+ fp.flock(File::LOCK_UN)
49
+ fp.close rescue nil
50
+ end
51
+ end
52
+
53
+ # Set storage file with given key, value
54
+ #
55
+ # StorageFile.set($setting.status_file, 'foo', 'bar') # like h['foo'] = 'bar'
56
+ # StorageFile.set($setting.status_file, ['a','b'], 'bar') # like h['a']['b'] = 'bar'
57
+ #
58
+ # @param [String] path
59
+ # @param [Object] key
60
+ # @param [Object] val
61
+ def self.set(path, key, val)
62
+ keys = Array(key)
63
+ open(path) do |fp|
64
+ params = fp.load
65
+ HashUtil.setdig(params, keys, val)
66
+ fp.dump(params)
67
+ end
68
+ end
69
+
70
+ # Set key to hold val if key does not exist
71
+ #
72
+ # StorageFile.setnx($setting.status_file, 'foo', 'bar') # like h['foo'] = 'bar'
73
+ # StorageFile.setnx($setting.status_file, ['a','b'], 'bar') # like h['a']['b'] = 'bar'
74
+ #
75
+ # @param [String] path
76
+ # @param [Object] key
77
+ # @param [Object] val
78
+ # @return [Boolean] true if set (not exist), false if not set (exists)
79
+ def self.setnx(path, key, val)
80
+ keys = Array(key)
81
+ open(path) do |fp|
82
+ params = fp.load
83
+ return false if params.dig(*keys)
84
+ HashUtil.setdig(params, keys, val)
85
+ fp.dump(params)
86
+ return true
87
+ end
88
+ end
89
+
90
+ # Set key to hold val if key does not exist and returns the holded value
91
+ #
92
+ # This is a kind of atomic short hand of
93
+ #
94
+ # StorageFile.setnx($setting.status_file, 'foo', 'bar')
95
+ # StorageFile.get($setting.status_file, 'foo')
96
+ #
97
+ # @param [String] path
98
+ # @param [Object] key
99
+ # @param [Object] val
100
+ # @return [Object] holded value
101
+ def self.getsetnx(path, key, val)
102
+ keys = Array(key)
103
+ open(path) do |fp|
104
+ params = fp.load
105
+ if curr = params.dig(*keys)
106
+ return curr
107
+ end
108
+ HashUtil.setdig(params, keys, val)
109
+ fp.dump(params)
110
+ return val
111
+ end
112
+ end
113
+
114
+ # Get value of the given key from storage file
115
+ #
116
+ # StorageFile.get($setting.status_file, 'foo') # like h['foo'] = 'bar'
117
+ # StorageFile.get($setting.status_file, ['a','b']) # like hash['a']['b']
118
+ #
119
+ # @param [String] path
120
+ # @param [Object] key
121
+ def self.get(path, key)
122
+ keys = Array(key)
123
+ open(path) {|fp| fp.load.dig(*keys) }
124
+ end
125
+
126
+ # Load storage file
127
+ #
128
+ # @return [Hash]
129
+ def load
130
+ if !(content = @fp.read).empty?
131
+ YAML.load(content) # all keys must be symbols
132
+ else
133
+ {}
134
+ end
135
+ end
136
+
137
+ # Dump to storage file
138
+ #
139
+ # @param [Hash] hash
140
+ def dump(hash)
141
+ File.write(@fp.path, YAML.dump(hash))
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,80 @@
1
+ module Triglav::Agent
2
+ # A timer utility to run serverengine worker in a time interval
3
+ #
4
+ # module Triglav::Agent
5
+ # module Worker
6
+ # def initialize
7
+ # @interval = 60.0 # sec
8
+ # end
9
+ #
10
+ # def run
11
+ # @timer = Timer.new
12
+ # @stop = false
13
+ # until @stop
14
+ # @timer.wait(@interval) { process }
15
+ # end
16
+ # end
17
+ #
18
+ # def stop
19
+ # @stop = true
20
+ # @timer.stop
21
+ # end
22
+ # end
23
+ # end
24
+ class Timer
25
+ def initialize
26
+ @r, @w = IO.pipe
27
+ start
28
+ end
29
+
30
+ def wait(sec, &block)
31
+ return if @stop
32
+ started = Time.now
33
+ yield
34
+ elapsed = Time.now - started
35
+ if (timeout = (sec - elapsed).to_f) > 0
36
+ begin
37
+ IO.select([@r], [], [], timeout)
38
+ rescue IOError, Errno::EBADF
39
+ # these error may occur if @r is closed during IO.select. Ignore it
40
+ end
41
+ end
42
+ end
43
+
44
+ def start
45
+ @stop = false
46
+ end
47
+
48
+ def stop
49
+ @stop = true
50
+ signal
51
+ end
52
+
53
+ private
54
+
55
+ def signal
56
+ @w.puts ' '
57
+ end
58
+
59
+ # # Hmm, Ctrl-C breaks condvar.wait before calling #stop unexpectedly
60
+ # attr_reader :condvar, :mutex
61
+ #
62
+ # def initialize
63
+ # @condvar = ConditionVariable.new
64
+ # @mutex = Mutex.new
65
+ # end
66
+ #
67
+ # def wait(sec, &block)
68
+ # started = Time.now
69
+ # @mutex.synchronize do
70
+ # yield
71
+ # elapsed = (Time.now - started).to_f
72
+ # @condvar.wait(@mutex, sec - elapsed)
73
+ # end
74
+ # end
75
+ #
76
+ # def signal
77
+ # @condvar.signal
78
+ # end
79
+ end
80
+ end
@@ -0,0 +1,5 @@
1
+ module Triglav
2
+ module Agent
3
+ VERSION = "1.0.0.pre1"
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ module Triglav
2
+ module Agent
3
+ end
4
+ end
5
+
6
+ require 'triglav/agent/api_client'
7
+ require 'triglav/agent/configuration'
8
+ require 'triglav/agent/error'
9
+ require 'triglav/agent/hash_util'
10
+ require 'triglav/agent/logger'
11
+ require 'triglav/agent/storage_file'
12
+ require 'triglav/agent/timer'
13
+ require 'triglav/agent/version'
14
+
15
+ require 'triglav/agent/base/cli'
16
+ require 'triglav/agent/base/setting'
17
+ require 'triglav/agent/base/worker'
18
+ require 'triglav/agent/base/processor'
19
+ require 'triglav/agent/base/connection' # just a skelton
20
+ require 'triglav/agent/base/monitor' # just a skelton
@@ -0,0 +1 @@
1
+ require 'triglav/agent'
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'triglav/agent/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "triglav-agent"
8
+ spec.version = Triglav::Agent::VERSION
9
+ spec.authors = ["Triglav Team"]
10
+ spec.email = ["triglav_admin_my@dena.jp"]
11
+
12
+ spec.summary = %q{Framework of Triglav Agent in Ruby.}
13
+ spec.description = %q{Framework of Triglav Agent in Ruby.}
14
+ spec.homepage = "https://github.com/triglav-dataflow/triglav-agent-framework-ruby"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "serverengine"
23
+ spec.add_dependency "dotenv"
24
+ spec.add_dependency "triglav_client"
25
+ spec.add_dependency "parallel"
26
+ spec.add_dependency "connection_pool"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.11"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ spec.add_development_dependency "test-unit"
31
+ spec.add_development_dependency "test-unit-rr"
32
+ spec.add_development_dependency "yard"
33
+ end