polyseerio 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +12 -0
- data/Gemfile +4 -0
- data/HISTORY.md +3 -0
- data/LICENSE +21 -0
- data/Makefile +43 -0
- data/README.md +307 -0
- data/lib/agent/agent.rb +35 -0
- data/lib/agent/default_config.rb +51 -0
- data/lib/agent/enum.rb +35 -0
- data/lib/agent/executor.rb +62 -0
- data/lib/agent/handler/event.rb +32 -0
- data/lib/agent/handler/expectation.rb +10 -0
- data/lib/agent/handler/fact.rb +18 -0
- data/lib/agent/handler/index.rb +15 -0
- data/lib/agent/handler/interface.rb +11 -0
- data/lib/agent/handler/metric.rb +23 -0
- data/lib/agent/handler/process.rb +10 -0
- data/lib/agent/helper.rb +137 -0
- data/lib/client.rb +47 -0
- data/lib/constant.rb +12 -0
- data/lib/enum.rb +82 -0
- data/lib/helper.rb +153 -0
- data/lib/middleware.rb +51 -0
- data/lib/polyseerio.rb +115 -0
- data/lib/request.rb +84 -0
- data/lib/resource/base.rb +73 -0
- data/lib/resource/definition.rb +166 -0
- data/lib/resource/factory.rb +149 -0
- data/lib/resource/helper.rb +91 -0
- data/lib/resource/routine.rb +26 -0
- data/lib/response.rb +27 -0
- data/lib/sdk/factory.rb +34 -0
- data/lib/sdk/helper.rb +50 -0
- data/lib/sdk/method/add_fact.rb +14 -0
- data/lib/sdk/method/add_gauge.rb +14 -0
- data/lib/sdk/method/attach.rb +26 -0
- data/lib/sdk/method/check.rb +11 -0
- data/lib/sdk/method/detach.rb +11 -0
- data/lib/sdk/method/execute.rb +11 -0
- data/lib/sdk/method/fact.rb +11 -0
- data/lib/sdk/method/gauge.rb +11 -0
- data/lib/sdk/method/index.rb +10 -0
- data/lib/sdk/method/message.rb +11 -0
- data/lib/sdk/method/remove.rb +11 -0
- data/lib/sdk/method/save.rb +32 -0
- data/lib/sdk/method/to_json.rb +11 -0
- data/lib/sdk/method/trigger.rb +17 -0
- data/lib/sdk/static/attach.rb +11 -0
- data/lib/sdk/static/check.rb +11 -0
- data/lib/sdk/static/create.rb +21 -0
- data/lib/sdk/static/detach.rb +11 -0
- data/lib/sdk/static/execute.rb +11 -0
- data/lib/sdk/static/find.rb +20 -0
- data/lib/sdk/static/find_by_id.rb +21 -0
- data/lib/sdk/static/find_by_name.rb +28 -0
- data/lib/sdk/static/index.rb +10 -0
- data/lib/sdk/static/message.rb +15 -0
- data/lib/sdk/static/remove.rb +21 -0
- data/lib/sdk/static/trigger.rb +17 -0
- data/lib/sdk/static/update.rb +18 -0
- data/lib/url_builder.rb +55 -0
- data/polyseerio.gemspec +32 -0
- metadata +205 -0
data/lib/agent/enum.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Polyseerio
|
2
|
+
module Agent
|
3
|
+
module Enum
|
4
|
+
module Expectation
|
5
|
+
IS_ALIVE = :is_alive
|
6
|
+
end
|
7
|
+
|
8
|
+
module Event
|
9
|
+
START = :start
|
10
|
+
STOP = :stop
|
11
|
+
end
|
12
|
+
|
13
|
+
module Fact
|
14
|
+
PID = :pid
|
15
|
+
GID = :gid
|
16
|
+
end
|
17
|
+
|
18
|
+
module Signal
|
19
|
+
SIGHUP = :HUP
|
20
|
+
SIGINT = :INT
|
21
|
+
SIGTERM = :TERM
|
22
|
+
end
|
23
|
+
|
24
|
+
module Process
|
25
|
+
EXIT = :exit
|
26
|
+
end
|
27
|
+
|
28
|
+
module Metric
|
29
|
+
MEMORY = :memory
|
30
|
+
CPU = :cpu
|
31
|
+
UPTIME = :uptime
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
require 'helper'
|
3
|
+
require 'resource/routine'
|
4
|
+
require 'agent/handler/index'
|
5
|
+
require 'agent/helper'
|
6
|
+
require 'agent/default_config'
|
7
|
+
|
8
|
+
module Polyseerio
|
9
|
+
module Agent
|
10
|
+
# Agent executor functions.
|
11
|
+
module Executor
|
12
|
+
# Setsup a client's agent.
|
13
|
+
def self.setup(client, options = {})
|
14
|
+
options = Polyseerio::Helper.defaults(options, DEFAULT_CONFIG)
|
15
|
+
|
16
|
+
Concurrent::Promise.new do
|
17
|
+
if options[:attach]
|
18
|
+
name = Helper.resolve_name(options)
|
19
|
+
|
20
|
+
# Resolve the instance.
|
21
|
+
# TODO: better handle failure to upsert.
|
22
|
+
instance = Resource::Routine.upsert(
|
23
|
+
client.Instance,
|
24
|
+
name: name
|
25
|
+
).execute.value
|
26
|
+
|
27
|
+
# Set the client's instance.
|
28
|
+
client.instance = instance
|
29
|
+
|
30
|
+
# Create a setup handler.
|
31
|
+
handler_options = Helper.extract_handler_options options
|
32
|
+
setup_handler = Helper.setup_with_handler(
|
33
|
+
Polyseerio::Agent::Handler::MAP,
|
34
|
+
client,
|
35
|
+
handler_options
|
36
|
+
)
|
37
|
+
|
38
|
+
# Gather setup operations.
|
39
|
+
setups = handler_options.map { |key, _| setup_handler.call(key) }
|
40
|
+
|
41
|
+
# Perform setups.
|
42
|
+
Concurrent::Promise.zip(*setups).execute.value
|
43
|
+
|
44
|
+
# Start monitoring.
|
45
|
+
instance.attach.execute.value
|
46
|
+
|
47
|
+
instance
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Tearsdown a client's agent.
|
53
|
+
def self.teardown(client, instance)
|
54
|
+
Concurrent::Promise.new do
|
55
|
+
teardown_handler('event', client)
|
56
|
+
|
57
|
+
instance.detach.excecute.value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'agent/enum'
|
2
|
+
|
3
|
+
module Polyseerio
|
4
|
+
module Agent
|
5
|
+
# Introduce event handlers.
|
6
|
+
module Handler
|
7
|
+
include Agent::Enum
|
8
|
+
|
9
|
+
def self.event
|
10
|
+
{
|
11
|
+
Event::START => proc do |_config, client|
|
12
|
+
client.Event.create(
|
13
|
+
name: "#{client.instance.name} agent has started.",
|
14
|
+
color: Polyseerio::Enum::Color::GREEN,
|
15
|
+
icon: Polyseerio::Enum::Icon::CHAIN
|
16
|
+
)
|
17
|
+
end,
|
18
|
+
|
19
|
+
Event::STOP => {
|
20
|
+
Interface::TEARDOWN => proc do |_config, client|
|
21
|
+
client.Event.create(
|
22
|
+
name: "#{client.instance.name} agent has stopped.",
|
23
|
+
color: Polyseerio::Enum::Color::ORANGE,
|
24
|
+
icon: Polyseerio::Enum::Icon::CHAIN_BROKER
|
25
|
+
)
|
26
|
+
end
|
27
|
+
}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Polyseerio
|
2
|
+
module Agent
|
3
|
+
# Introduce fact handlers.
|
4
|
+
module Handler
|
5
|
+
def self.fact
|
6
|
+
{
|
7
|
+
Fact::PID => proc do |_config, client|
|
8
|
+
client.instance.set_fact('pid', ::Process.pid)
|
9
|
+
end,
|
10
|
+
|
11
|
+
Fact::GID => proc do |_config, client|
|
12
|
+
client.instance.set_fact('gid', ::Process.gid)
|
13
|
+
end
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Polyseerio
|
4
|
+
module Agent
|
5
|
+
# Contains handlers and handler map.
|
6
|
+
module Handler
|
7
|
+
MAP = Polyseerio::Helper.dir_proc_map(File.dirname(__FILE__), self)
|
8
|
+
|
9
|
+
# Extracts handler type options from agent options.
|
10
|
+
def self.extract_options(options)
|
11
|
+
options.select { |key, _| MAP.key? key }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Polyseerio
|
2
|
+
module Agent
|
3
|
+
# Introduce metric handlers.
|
4
|
+
module Handler
|
5
|
+
def self.metric
|
6
|
+
{
|
7
|
+
Metric::MEMORY => proc do |_config, client|
|
8
|
+
client.instance.add_gauge 'memory', 0
|
9
|
+
end,
|
10
|
+
|
11
|
+
Metric::CPU => proc do |_config, client|
|
12
|
+
client.instance.add_gauge 'cpu_user', 0
|
13
|
+
client.instance.add_gauge 'cpu_system', 0
|
14
|
+
end,
|
15
|
+
|
16
|
+
Metric::UPTIME => proc do |_config, client|
|
17
|
+
client.instance.add_gauge 'uptime', 0
|
18
|
+
end
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/agent/helper.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'functional'
|
2
|
+
require 'concurrent'
|
3
|
+
require 'agent/handler/index'
|
4
|
+
require 'agent/handler/interface'
|
5
|
+
|
6
|
+
module Polyseerio
|
7
|
+
module Agent
|
8
|
+
# Helper functions for Agent
|
9
|
+
module Helper
|
10
|
+
# Returns an iterator for a handler subtype.
|
11
|
+
def self.create_subtype_iterator(handlers, iteratee, *args)
|
12
|
+
proc do |key, value|
|
13
|
+
if handlers.key? key.to_sym # TODO: unit-test to_sym
|
14
|
+
iteratee.call(handlers, key, value, *args)
|
15
|
+
else
|
16
|
+
Concurrent::Promise.reject('Could not find a handler subtype: ' \
|
17
|
+
"#{key}.")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a handler function.
|
23
|
+
def self.create_handler(iteratee)
|
24
|
+
proc do |map, client, config, type, *args|
|
25
|
+
if map.key? type.to_sym
|
26
|
+
if config.key? type
|
27
|
+
# TODO: unit-test passed args
|
28
|
+
work = config.fetch(type)
|
29
|
+
.map(&iteratee.call(map.fetch(type), client, *args))
|
30
|
+
|
31
|
+
Concurrent::Promise.zip(*work)
|
32
|
+
else
|
33
|
+
Concurrent::Promise.fulfill []
|
34
|
+
end
|
35
|
+
else
|
36
|
+
Concurrent::Promise.reject('Could not find a handler type: ' \
|
37
|
+
"#{type}.")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a setup handler function.
|
43
|
+
@setup = proc do |handlers_outer, *args_outer|
|
44
|
+
setup_iterator = proc do |handlers, key, value, *args|
|
45
|
+
handler = handlers.fetch(key)
|
46
|
+
|
47
|
+
if handler.respond_to? :call
|
48
|
+
handler.call(value, *args) # TODO: unit-test passed args
|
49
|
+
elsif handler.key? Handler::Interface::SETUP
|
50
|
+
# TODO: unit-test passed args
|
51
|
+
handler[Handler::Interface::SETUP].call(value, *args)
|
52
|
+
else
|
53
|
+
Concurrent::Promise.fulfill
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
create_subtype_iterator(handlers_outer, setup_iterator, *args_outer)
|
58
|
+
end
|
59
|
+
|
60
|
+
@teardown = proc do |handlers_outer, *args_outer|
|
61
|
+
teardown_iterator = proc do |handlers, key, _value, *args|
|
62
|
+
if handlers.fetch(key).key? Handler::Interface::TEARDOWN
|
63
|
+
handlers.fetch(key).fetch(Handler::Interface::TEARDOWN).call(*args)
|
64
|
+
else
|
65
|
+
Concurrent::Promise.fulfill
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
create_subtype_iterator(handlers_outer, teardown_iterator, *args_outer)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Sets up a handler type.
|
73
|
+
def self.setup_with_handler(*args)
|
74
|
+
create_handler(@setup).curry.call(*args)
|
75
|
+
end
|
76
|
+
|
77
|
+
# Tears down a handler type.
|
78
|
+
def self.teardown_with_handler(*args)
|
79
|
+
create_handler(@teardown).curry.call(*args)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns a unique name.
|
83
|
+
def self.generate_name
|
84
|
+
'ruby-instance'
|
85
|
+
end
|
86
|
+
|
87
|
+
# Reduce handler options based on if they are enabled.
|
88
|
+
def self.reduce_handler_option
|
89
|
+
proc do |(name, config), acc|
|
90
|
+
acc[name] = config if handle? config
|
91
|
+
|
92
|
+
acc
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Given handler options, enabled subtype options are returned.
|
97
|
+
def self.filter_enabled_handler_options(options)
|
98
|
+
options.each_with_object({}, &reduce_handler_option)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Given agent options, handlers options are returned.
|
102
|
+
def self.filter_handlers(options)
|
103
|
+
options.each_with_object({}) do |(name, config), acc|
|
104
|
+
acc[name] = filter_enabled_handler_options config
|
105
|
+
|
106
|
+
acc
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Extracts handler options and then filters them based on if they
|
111
|
+
# are enabled or not. TODO: unit-test or integration-test
|
112
|
+
def self.extract_handler_options(options)
|
113
|
+
options = Handler.extract_options options
|
114
|
+
|
115
|
+
filter_handlers options
|
116
|
+
end
|
117
|
+
|
118
|
+
# Determines if a handler configuration should be handled.
|
119
|
+
def self.handle?(value)
|
120
|
+
return value if value == true
|
121
|
+
|
122
|
+
if Functional::TypeCheck::Type?(value, Hash) && (value.key? :enabled)
|
123
|
+
return value[:enabled]
|
124
|
+
end
|
125
|
+
|
126
|
+
false
|
127
|
+
end
|
128
|
+
|
129
|
+
# Given an agent config a name will be returned.
|
130
|
+
def self.resolve_name(config)
|
131
|
+
return config[:name] if config.key?(:name) && !config[:name].nil?
|
132
|
+
|
133
|
+
generate_name
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/lib/client.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'agent/agent'
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
module Polyseerio
|
5
|
+
# The Polyseer.io client.
|
6
|
+
class Client
|
7
|
+
INITIALIZE_DEFAULTS = {
|
8
|
+
agent_class: Agent::Agent,
|
9
|
+
request: nil
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
attr_accessor :cid, :agent, :instance
|
13
|
+
attr_writer :instance
|
14
|
+
|
15
|
+
def initialize(cid, options = {})
|
16
|
+
options = Helper.defaults(options, INITIALIZE_DEFAULTS)
|
17
|
+
|
18
|
+
if options[:request].nil?
|
19
|
+
raise ArgumentError, 'Cannot create an instance of Client without' \
|
20
|
+
'passing a request instance.'
|
21
|
+
end
|
22
|
+
|
23
|
+
if options.key? :resources
|
24
|
+
options[:resources].each(&Helper.attach_to_instance!(self))
|
25
|
+
end
|
26
|
+
|
27
|
+
@cid = cid
|
28
|
+
@agent = nil
|
29
|
+
@instance = nil
|
30
|
+
@request = options[:request]
|
31
|
+
@agent_class = options[:agent_class]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Start an agent using this client.
|
35
|
+
def start_agent(*args)
|
36
|
+
raise 'Agent has already started.' unless @agent.nil?
|
37
|
+
|
38
|
+
@agent = @agent_class.new(self)
|
39
|
+
|
40
|
+
@agent.start(*args)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_accessor :request, :agent_class
|
46
|
+
end
|
47
|
+
end
|
data/lib/constant.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Polyseerio
|
2
|
+
module Constant
|
3
|
+
ACCESS_TOKEN_HEADER = 'X-AUTH-HEADER'.freeze
|
4
|
+
DEFAULT_API_BASE_URL = 'api.polyseer.io/polyseer'.freeze
|
5
|
+
DEFAULT_API_PROTOCOL = 'https://'.freeze
|
6
|
+
DEFAULT_API_VERSION = 'v1'.freeze
|
7
|
+
DEFAULT_ENV = 'RAILS_ENV'.freeze
|
8
|
+
DEFAULT_ENVIRONMENT = 'development'.freeze
|
9
|
+
DEFAULT_TIMEOUT = 10_000
|
10
|
+
DEFAULT_TOKEN_ENV = 'POLYSEERIO_TOKEN'.freeze
|
11
|
+
end
|
12
|
+
end
|
data/lib/enum.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Polyseerio
|
4
|
+
module Enum
|
5
|
+
# Contains resource routes.
|
6
|
+
module Resource
|
7
|
+
ALERT = 'alerts'.freeze
|
8
|
+
CHANNEL = 'channels'.freeze
|
9
|
+
ENVIRONMENT = 'environments'.freeze
|
10
|
+
EVENT = 'events'.freeze
|
11
|
+
EXPECTATION = 'expectations'.freeze
|
12
|
+
INSTANCE = 'instances'.freeze
|
13
|
+
LOGIC_BLOCK = 'logic-blocks'.freeze
|
14
|
+
MEMBER = 'members'.freeze
|
15
|
+
MESSAGE = 'messages'.freeze
|
16
|
+
SETTING = 'settings'.freeze
|
17
|
+
TASK = 'tasks'.freeze
|
18
|
+
end
|
19
|
+
|
20
|
+
# Contains type constants for use with API calls.
|
21
|
+
module Type
|
22
|
+
Resource.constants.each do |key|
|
23
|
+
value = Helper.resource_to_type Resource.const_get(key)
|
24
|
+
|
25
|
+
const_set(key, value)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module Determiner
|
30
|
+
ONE = 'one'.freeze
|
31
|
+
SOME = 'some'.freeze
|
32
|
+
end
|
33
|
+
|
34
|
+
module Direction
|
35
|
+
INBOUND = 'inbound'.freeze
|
36
|
+
OUTBOUND = 'outbound'.freeze
|
37
|
+
end
|
38
|
+
|
39
|
+
module Subtype
|
40
|
+
LONG_RUNNING = 'long_running'.freeze
|
41
|
+
PERIODIC = 'periodic'.freeze
|
42
|
+
end
|
43
|
+
|
44
|
+
module Color
|
45
|
+
BLUE = 'blue'.freeze
|
46
|
+
BROWN = 'brown'.freeze
|
47
|
+
GREEN = 'green'.freeze
|
48
|
+
ORANGE = 'orange'.freeze
|
49
|
+
PURPLE = 'purple'.freeze
|
50
|
+
RED = 'red'.freeze
|
51
|
+
TEAL = 'teal'.freeze
|
52
|
+
WHITE = 'white'.freeze
|
53
|
+
YELLOW = 'yellow'.freeze
|
54
|
+
NONE = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
module Icon
|
58
|
+
THUMBS_UP = 'thumbs-up'.freeze
|
59
|
+
CALENDAR = 'calendar'.freeze
|
60
|
+
SERVER = 'server'.freeze
|
61
|
+
SIGNAL = 'wifi'.freeze
|
62
|
+
GIT = 'git'.freeze
|
63
|
+
CODE = 'code'.freeze
|
64
|
+
CHECK = 'check'.freeze
|
65
|
+
ERROR = 'exclamation-triangle'.freeze
|
66
|
+
PENCIL = 'pencil'.freeze
|
67
|
+
CHAIN = 'chain'.freeze
|
68
|
+
CHAIN_BROKEN = 'chain-broken'.freeze
|
69
|
+
NONE = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
module Protocol
|
73
|
+
SMTP = 'smtp'.freeze
|
74
|
+
SMS = 'sms'.freeze
|
75
|
+
end
|
76
|
+
|
77
|
+
module Strategy
|
78
|
+
FALLBACK = :fallback
|
79
|
+
ID = :id
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|