polyseerio 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,153 @@
1
+ require 'inflection'
2
+
3
+ module Polyseerio
4
+ # General helper functions for SDK
5
+ module Helper
6
+ DEFAULT_REQUIRE_DIRECTORY_OPTIONS = {
7
+ exclude: ['index'].freeze
8
+ }.freeze
9
+
10
+ # Simple conversion to seconds from ms.
11
+ def self.ms_to_seconds(ms)
12
+ ms / 1000.0
13
+ end
14
+
15
+ # Given directory and module a map of module procs will be created.
16
+ # TODO: this is really a dir func map not a proc map
17
+ def self.dir_proc_map(dir, mod)
18
+ map = Polyseerio::Helper.dir_to_path_map dir
19
+
20
+ map.each { |(_, path)| require path }
21
+
22
+ map.each_with_object({}, &Helper.add_to_proc_map(mod))
23
+ end
24
+
25
+ # Adds a proc method to an accumulator by its name.
26
+ # TODO: this is really a dir func map not always a proc map.
27
+ def self.add_to_proc_map(*args)
28
+ proc do |mod, (name, _), acc|
29
+ if mod.respond_to? name
30
+ result = mod.send name
31
+
32
+ acc[name] = result unless result.nil?
33
+ end
34
+
35
+ acc
36
+ end.curry.call(*args)
37
+ end
38
+
39
+ # Convert resource string to resource type.
40
+ def self.resource_to_type(resource)
41
+ Inflection.singular(resource)
42
+ end
43
+
44
+ # A memoize function that has an optional cache key.
45
+ def self.memoize_function(func, get_key)
46
+ lambda do
47
+ results = {}
48
+
49
+ proc do |*args|
50
+ key = get_key.call(*args) # TODO: assert key is sym?
51
+
52
+ if results.key? key
53
+ results.fetch key
54
+ else
55
+ result = func.call(*args)
56
+
57
+ results[key] = result
58
+
59
+ result
60
+ end
61
+ end
62
+ end.call
63
+ end
64
+
65
+ # Simple identity function.
66
+ def self.identity(value)
67
+ proc { |x| x }.call(value)
68
+ end
69
+
70
+ # Maps filename to file path
71
+ def self.dir_to_path_map(directory, options = {})
72
+ directory = "#{directory}/*#{options[:extension]}"
73
+ options = defaults(options, DEFAULT_REQUIRE_DIRECTORY_OPTIONS)
74
+
75
+ paths = Dir[directory].select do |file|
76
+ name = File.basename(file, '.*')
77
+
78
+ !options[:exclude].include? name
79
+ end
80
+
81
+ paths.each_with_object({}) do |file, acc|
82
+ name = File.basename(file, '.*')
83
+
84
+ acc[name.to_sym] = file
85
+
86
+ acc
87
+ end
88
+ end
89
+
90
+ # Load an include an entire directory.
91
+ def self.require_directory(directory, options = {})
92
+ directory = "#{directory}/*#{options[:extension]}"
93
+ options = defaults(options, DEFAULT_REQUIRE_DIRECTORY_OPTIONS)
94
+
95
+ Dir[directory].select do |file|
96
+ pathname = Pathname.new(file)
97
+
98
+ !options[:exclude].include? pathname.basename
99
+ end
100
+ end
101
+
102
+ # Format a resouce payload for API consumption
103
+ def self.format_payload(payload)
104
+ { data: { attributes: payload.clone } }
105
+ end
106
+
107
+ # Attempt to geta token.
108
+ def self.resolve_token(options)
109
+ return options[:token] unless options[:token].nil?
110
+
111
+ if ENV.key? options[:token_env]
112
+ value = ENV.fetch(options[:token_env], nil)
113
+
114
+ return value unless value.nil?
115
+ end
116
+
117
+ nil
118
+ end
119
+
120
+ # Generates default options.
121
+ def self.defaults(options, *defaults)
122
+ result = {}
123
+
124
+ defaults.reverse_each do |opts|
125
+ result.merge!(opts)
126
+ end
127
+
128
+ result.merge!(options)
129
+ end
130
+
131
+ # Used to attach a method to an instance
132
+ def self.attach_to_instance!(*args)
133
+ lambda do |instance, (key, value)|
134
+ instance.instance_eval do
135
+ define_singleton_method(key, proc { value })
136
+ end
137
+ end.curry.call(*args)
138
+ end
139
+
140
+ # Rekey a hash using a remapping hash.
141
+ def self.rekey(hash, map)
142
+ hash.each_with_object({}) do |(key, value), acc|
143
+ if map.key? key
144
+ acc[map[key]] = value
145
+ else
146
+ acc[key] = value
147
+ end
148
+
149
+ acc
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,51 @@
1
+ require 'helper'
2
+ require 'json'
3
+ require 'response'
4
+ require 'resource/helper'
5
+
6
+ module Polyseerio
7
+ module Middleware
8
+ # Pre request middleware.
9
+ module Pre
10
+ # Requests arguments run through there.
11
+ def self.format_arguments
12
+ proc do |*args|
13
+ new_args = args
14
+
15
+ if new_args.size > 1
16
+ new_args[1] = Helper.format_payload new_args[1]
17
+ new_args[1] = new_args[1].to_json
18
+ end
19
+
20
+ new_args
21
+ end
22
+ end
23
+ end
24
+
25
+ # Post request middleware.
26
+ module Post
27
+ # Takes rest-client and response and converts it to internal response.
28
+ def self.to_response
29
+ proc do |response|
30
+ Response.new(response)
31
+ end
32
+ end
33
+
34
+ # Request results run through there.
35
+ def self.parse_response
36
+ proc do |response|
37
+ Resource::Helper.parse_response(response, 0) # TODO: need a cid
38
+ end
39
+ end
40
+ end
41
+
42
+ # Request rejection (error) middleware.
43
+ module Reject
44
+ def self.handle_rejection
45
+ proc do |error|
46
+ error
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,115 @@
1
+ require 'resource/factory'
2
+ require 'request'
3
+ require 'middleware'
4
+ require 'constant'
5
+ require 'enum'
6
+ require 'client'
7
+ require 'url_builder'
8
+ require 'rest-client'
9
+ require 'helper'
10
+
11
+ # Main Polyseerio module.
12
+ module Polyseerio
13
+ # Default client options.
14
+ DEFAULT_CLIENT_OPTIONS = {
15
+ agent: {},
16
+ deduce: true,
17
+ env: Constant::DEFAULT_ENV,
18
+ timeout: Constant::DEFAULT_TIMEOUT,
19
+ environment: Constant::DEFAULT_ENVIRONMENT,
20
+ token: nil,
21
+ token_env: Constant::DEFAULT_TOKEN_ENV,
22
+ upsert_env: true,
23
+ version: Constant::DEFAULT_API_VERSION
24
+ }.freeze
25
+
26
+ # Required resources for constructing a client.
27
+ REQUIRED_RESOURCES = [
28
+ Enum::Resource::ALERT,
29
+ Enum::Resource::CHANNEL,
30
+ Enum::Resource::ENVIRONMENT,
31
+ Enum::Resource::EVENT,
32
+ Enum::Resource::EXPECTATION,
33
+ Enum::Resource::INSTANCE,
34
+ Enum::Resource::LOGIC_BLOCK,
35
+ Enum::Resource::MEMBER,
36
+ Enum::Resource::SETTING,
37
+ Enum::Resource::TASK
38
+ ].freeze
39
+
40
+ # Maps resources to paths within a Client
41
+ CLIENT_RESOURCE_PATHS = {
42
+ Enum::Resource::ALERT => :Alert,
43
+ Enum::Resource::CHANNEL => :Channel,
44
+ Enum::Resource::ENVIRONMENT => :Environment,
45
+ Enum::Resource::EVENT => :Event,
46
+ Enum::Resource::EXPECTATION => :Expectation,
47
+ Enum::Resource::INSTANCE => :Instance,
48
+ Enum::Resource::LOGIC_BLOCK => :LogicBlock,
49
+ Enum::Resource::MEMBER => :Member,
50
+ Enum::Resource::SETTING => :Settings,
51
+ Enum::Resource::TASK => :Task
52
+ }.freeze
53
+
54
+ # Create a client and start it's agent.
55
+ def self.start(*args)
56
+ client = make(*args)
57
+
58
+ client.start_agent
59
+ end
60
+
61
+ @make_call_count = 0
62
+
63
+ # Create a client.
64
+ def self.make(options = {})
65
+ options = Helper.defaults(options, DEFAULT_CLIENT_OPTIONS)
66
+
67
+ cid = @make_call_count
68
+
69
+ token = Helper.resolve_token options
70
+
71
+ base_url = URL.get_base_url(
72
+ Constant::DEFAULT_API_BASE_URL,
73
+ Constant::DEFAULT_API_PROTOCOL,
74
+ options[:version]
75
+ )
76
+
77
+ if token.nil?
78
+ raise ArgumentError, 'Could not find an access token. None was passed' \
79
+ 'and non could be found in the environment variable: ' \
80
+ "#{options[:token_env]}."
81
+ end
82
+
83
+ headers = {
84
+ Constant::ACCESS_TOKEN_HEADER => token,
85
+ :content_type => 'application/json'
86
+ }
87
+
88
+ rest_resource = RestClient::Resource.new(
89
+ base_url,
90
+ headers: headers,
91
+ timeout: Helper.ms_to_seconds(options[:timeout])
92
+ )
93
+
94
+ # Create a request instance that uses middleware.
95
+ request = Request.new(
96
+ rest_resource,
97
+ pre: [Middleware::Pre.format_arguments],
98
+ post: [Middleware::Post.to_response, Middleware::Post.parse_response]
99
+ )
100
+
101
+ resources = REQUIRED_RESOURCES.each_with_object({}) do |resource, acc|
102
+ acc[resource] = Resource::Factory.make(resource, request, cid, options)
103
+
104
+ acc
105
+ end
106
+
107
+ resources = Helper.rekey(resources, CLIENT_RESOURCE_PATHS)
108
+
109
+ client = Client.new(cid, request: request, resources: resources)
110
+
111
+ @make_call_count += 1
112
+
113
+ client
114
+ end
115
+ end
@@ -0,0 +1,84 @@
1
+ require 'helper'
2
+ require 'concurrent'
3
+
4
+ module Polyseerio
5
+ # HTTP request wrapper that can use attached middleware.
6
+ class Request
7
+ module Middleware
8
+ PRE = :pre
9
+ POST = :post
10
+ REJECT = :reject
11
+ end
12
+
13
+ INITIALIZE_DEFAULTS = {
14
+ Middleware::PRE => [],
15
+ Middleware::POST => [],
16
+ Middleware::REJECT => []
17
+ }.freeze
18
+
19
+ def initialize(resource, options = {})
20
+ # need to ensure taht pre, post, reject are all arrays otherwise raise
21
+ options = Helper.defaults(options, INITIALIZE_DEFAULTS)
22
+
23
+ @resource = resource
24
+
25
+ @pre_request = options[Middleware::PRE]
26
+ @post_request = options[Middleware::POST]
27
+ @reject_request = options[Middleware::REJECT]
28
+ end
29
+
30
+ # Perform a GET request.
31
+ def get(*args)
32
+ execute(:get, *args)
33
+ end
34
+
35
+ # Perform a POST request.
36
+ def post(*args)
37
+ execute(:post, *args)
38
+ end
39
+
40
+ # Perform a PUT request.
41
+ def put(*args)
42
+ execute(:put, *args)
43
+ end
44
+
45
+ # Perform a DELETE request.
46
+ def delete(*args)
47
+ execute(:delete, *args)
48
+ end
49
+
50
+ private
51
+
52
+ # Execute a request using pre, post, and reject middleware.
53
+ #
54
+ # method - The HTTP method.
55
+ # ... - Arguments to forward to execute.
56
+ #
57
+ # Returns a promise.
58
+ def execute(method, *args)
59
+ new_args = args
60
+
61
+ @pre_request.each do |middleware|
62
+ new_args = middleware.call(*new_args)
63
+ end
64
+
65
+ path = new_args.empty? ? '' : new_args.shift
66
+
67
+ req = proc do ||
68
+ @resource[path].send(method, *new_args)
69
+ end
70
+
71
+ post = proc do |result|
72
+ @post_request.each do |middleware|
73
+ result = middleware.call(result)
74
+ end
75
+
76
+ result
77
+ end
78
+
79
+ Concurrent::Promise.new(&req).on_success(&post)
80
+ end
81
+
82
+ attr_accessor :resource, :pre_request, :post_request, :reject_request
83
+ end
84
+ end
@@ -0,0 +1,73 @@
1
+ require 'sdk/helper'
2
+
3
+ module Polyseerio
4
+ module Resource
5
+ # Base class for any resource.
6
+ class Base
7
+ attr_accessor :eid
8
+ attr_writer :eid
9
+
10
+ def initialize(attributes = {})
11
+ @eid = if attributes.include? :eid
12
+ attributes[:eid]
13
+ else
14
+ Polyseerio::SDK::Helper.resolve_eid(copts)
15
+ end
16
+ @attributes = attributes
17
+ end
18
+
19
+ # Set a property hash on the instance.
20
+ def override_properties(properties)
21
+ properties.each_with_object(self) do |(key, value), this|
22
+ this.send(:"#{key}=", value)
23
+ end
24
+ end
25
+
26
+ # Returns a copy of class attributes.
27
+ def properties
28
+ attributes.clone
29
+ end
30
+
31
+ # Returns the type of the class.
32
+ def type
33
+ self.class.type
34
+ end
35
+
36
+ # Returns the client options this class was constructed with.
37
+ def copts
38
+ self.class.copts
39
+ end
40
+
41
+ # Returns the client's request object.
42
+ def request
43
+ self.class.request
44
+ end
45
+
46
+ # True if the resource is new (not yet saved).
47
+ def new?
48
+ id.nil?
49
+ end
50
+
51
+ def method_missing(name, *args) # rubocop:disable all
52
+ # Setter.
53
+ if name =~ /^(\w+)=$/
54
+ name = :"#{$1}" # rubocop:disable all
55
+
56
+ @attributes[:"#{$1}"] = args[0] # rubocop:disable all
57
+ end
58
+
59
+ # Getter.
60
+ @attributes.fetch(name, nil)
61
+ end
62
+
63
+ def respond_to_missing?(_method_name)
64
+ true
65
+ end
66
+
67
+ private
68
+
69
+ attr_accessor :attributes
70
+ attr_writer :attributes
71
+ end
72
+ end
73
+ end