polyseerio 0.0.1

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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +12 -0
  4. data/Gemfile +4 -0
  5. data/HISTORY.md +3 -0
  6. data/LICENSE +21 -0
  7. data/Makefile +43 -0
  8. data/README.md +307 -0
  9. data/lib/agent/agent.rb +35 -0
  10. data/lib/agent/default_config.rb +51 -0
  11. data/lib/agent/enum.rb +35 -0
  12. data/lib/agent/executor.rb +62 -0
  13. data/lib/agent/handler/event.rb +32 -0
  14. data/lib/agent/handler/expectation.rb +10 -0
  15. data/lib/agent/handler/fact.rb +18 -0
  16. data/lib/agent/handler/index.rb +15 -0
  17. data/lib/agent/handler/interface.rb +11 -0
  18. data/lib/agent/handler/metric.rb +23 -0
  19. data/lib/agent/handler/process.rb +10 -0
  20. data/lib/agent/helper.rb +137 -0
  21. data/lib/client.rb +47 -0
  22. data/lib/constant.rb +12 -0
  23. data/lib/enum.rb +82 -0
  24. data/lib/helper.rb +153 -0
  25. data/lib/middleware.rb +51 -0
  26. data/lib/polyseerio.rb +115 -0
  27. data/lib/request.rb +84 -0
  28. data/lib/resource/base.rb +73 -0
  29. data/lib/resource/definition.rb +166 -0
  30. data/lib/resource/factory.rb +149 -0
  31. data/lib/resource/helper.rb +91 -0
  32. data/lib/resource/routine.rb +26 -0
  33. data/lib/response.rb +27 -0
  34. data/lib/sdk/factory.rb +34 -0
  35. data/lib/sdk/helper.rb +50 -0
  36. data/lib/sdk/method/add_fact.rb +14 -0
  37. data/lib/sdk/method/add_gauge.rb +14 -0
  38. data/lib/sdk/method/attach.rb +26 -0
  39. data/lib/sdk/method/check.rb +11 -0
  40. data/lib/sdk/method/detach.rb +11 -0
  41. data/lib/sdk/method/execute.rb +11 -0
  42. data/lib/sdk/method/fact.rb +11 -0
  43. data/lib/sdk/method/gauge.rb +11 -0
  44. data/lib/sdk/method/index.rb +10 -0
  45. data/lib/sdk/method/message.rb +11 -0
  46. data/lib/sdk/method/remove.rb +11 -0
  47. data/lib/sdk/method/save.rb +32 -0
  48. data/lib/sdk/method/to_json.rb +11 -0
  49. data/lib/sdk/method/trigger.rb +17 -0
  50. data/lib/sdk/static/attach.rb +11 -0
  51. data/lib/sdk/static/check.rb +11 -0
  52. data/lib/sdk/static/create.rb +21 -0
  53. data/lib/sdk/static/detach.rb +11 -0
  54. data/lib/sdk/static/execute.rb +11 -0
  55. data/lib/sdk/static/find.rb +20 -0
  56. data/lib/sdk/static/find_by_id.rb +21 -0
  57. data/lib/sdk/static/find_by_name.rb +28 -0
  58. data/lib/sdk/static/index.rb +10 -0
  59. data/lib/sdk/static/message.rb +15 -0
  60. data/lib/sdk/static/remove.rb +21 -0
  61. data/lib/sdk/static/trigger.rb +17 -0
  62. data/lib/sdk/static/update.rb +18 -0
  63. data/lib/url_builder.rb +55 -0
  64. data/polyseerio.gemspec +32 -0
  65. metadata +205 -0
@@ -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,10 @@
1
+ module Polyseerio
2
+ module Agent
3
+ # Introduce expectation handlers.
4
+ module Handler
5
+ def self.expectation
6
+ {}
7
+ end
8
+ end
9
+ end
10
+ 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,11 @@
1
+ module Polyseerio
2
+ module Agent
3
+ module Handler
4
+ # Interface used for handlers.
5
+ module Interface
6
+ SETUP = :setup
7
+ TEARDOWN = :teardown
8
+ end
9
+ end
10
+ end
11
+ 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
@@ -0,0 +1,10 @@
1
+ module Polyseerio
2
+ module Agent
3
+ # Introduce process handlers.
4
+ module Handler
5
+ def self.process
6
+ {}
7
+ end
8
+ end
9
+ end
10
+ end
@@ -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
@@ -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
@@ -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
@@ -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