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,166 @@
1
+ require 'enum'
2
+
3
+ module Polyseerio
4
+ # Defines polyseer.io resources
5
+ module Resource
6
+ module Definition
7
+ STATICS = :statics
8
+ METHODS = :methods
9
+
10
+ CREATABLE_STATICS = [
11
+ :create
12
+ ].freeze
13
+ READABLE_STATICS = [
14
+ :find,
15
+ :find_by_id
16
+ ].freeze
17
+ DELETABLE_STATICS = [
18
+ :remove
19
+ ].freeze
20
+ UPDATABLE_STATICS = [
21
+ :update
22
+ ].freeze
23
+ CRUD_STATICS = [
24
+ *CREATABLE_STATICS,
25
+ *READABLE_STATICS,
26
+ *DELETABLE_STATICS,
27
+ *UPDATABLE_STATICS
28
+ ].freeze
29
+
30
+ RESOURCE_INSTANCE = [
31
+ :to_json
32
+ ].freeze
33
+
34
+ SAVABLE_INSTANCE = [
35
+ :save
36
+ ].freeze
37
+
38
+ DEFINITION = {
39
+ Enum::Resource::ALERT => {
40
+ STATICS => [
41
+ *CRUD_STATICS,
42
+ :find_by_name,
43
+ :trigger
44
+ ],
45
+ METHODS => [
46
+ *SAVABLE_INSTANCE,
47
+ *RESOURCE_INSTANCE,
48
+ :trigger,
49
+ :remove
50
+ ]
51
+ },
52
+ Enum::Resource::CHANNEL => {
53
+ STATICS => [
54
+ *CRUD_STATICS,
55
+ :find_by_name,
56
+ :message
57
+ ],
58
+ METHODS => [
59
+ *SAVABLE_INSTANCE,
60
+ *RESOURCE_INSTANCE,
61
+ :message,
62
+ :remove
63
+ ]
64
+ },
65
+ Enum::Resource::ENVIRONMENT => {
66
+ STATICS => [
67
+ *CRUD_STATICS,
68
+ :find_by_name,
69
+ :message
70
+ ],
71
+ METHODS => [
72
+ *SAVABLE_INSTANCE,
73
+ *RESOURCE_INSTANCE,
74
+ :message,
75
+ :remove
76
+ ]
77
+ },
78
+ Enum::Resource::EVENT => {
79
+ STATICS => [
80
+ *CREATABLE_STATICS,
81
+ *READABLE_STATICS
82
+ ],
83
+ METHODS => [
84
+ *SAVABLE_INSTANCE,
85
+ *RESOURCE_INSTANCE
86
+ ]
87
+ },
88
+ Enum::Resource::EXPECTATION => {
89
+ STATICS => [
90
+ *CRUD_STATICS,
91
+ :find_by_name,
92
+ :check
93
+ ],
94
+ METHODS => [
95
+ *SAVABLE_INSTANCE,
96
+ *RESOURCE_INSTANCE,
97
+ :remove,
98
+ :check
99
+ ]
100
+ },
101
+ Enum::Resource::INSTANCE => {
102
+ STATICS => [
103
+ *CRUD_STATICS,
104
+ :find_by_name,
105
+ :attach
106
+ ],
107
+ METHODS => [
108
+ *SAVABLE_INSTANCE,
109
+ *RESOURCE_INSTANCE,
110
+ :add_gauge,
111
+ :attach,
112
+ :detach,
113
+ :fact,
114
+ :gauge,
115
+ :remove,
116
+ :add_fact
117
+ ]
118
+ },
119
+ Enum::Resource::LOGIC_BLOCK => {
120
+ STATICS => [
121
+ *CRUD_STATICS,
122
+ :execute
123
+ ],
124
+ METHODS => [
125
+ *SAVABLE_INSTANCE,
126
+ *RESOURCE_INSTANCE,
127
+ :remove,
128
+ :execute
129
+ ]
130
+ },
131
+ Enum::Resource::MEMBER => {
132
+ STATICS => [
133
+ *CRUD_STATICS
134
+ ],
135
+ METHODS => [
136
+ *SAVABLE_INSTANCE,
137
+ *RESOURCE_INSTANCE,
138
+ :remove
139
+ ]
140
+ },
141
+ Enum::Resource::MESSAGE => {
142
+ STATICS => [
143
+ *CRUD_STATICS
144
+ ],
145
+ METHODS => [
146
+ *SAVABLE_INSTANCE,
147
+ *RESOURCE_INSTANCE
148
+ ]
149
+ },
150
+ Enum::Resource::SETTING => {
151
+ STATICS => []
152
+ },
153
+ Enum::Resource::TASK => {
154
+ STATICS => [
155
+ *CRUD_STATICS
156
+ ],
157
+ METHODS => [
158
+ *SAVABLE_INSTANCE,
159
+ *RESOURCE_INSTANCE,
160
+ :remove
161
+ ]
162
+ }
163
+ }.freeze
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,149 @@
1
+ require 'resource/definition'
2
+ require 'resource/helper'
3
+ require 'resource/base'
4
+ require 'sdk/factory'
5
+ require 'inflection'
6
+ require 'sdk/helper'
7
+
8
+ module Polyseerio
9
+ module Resource
10
+ # Resource building methods.
11
+ module Factory
12
+ # Determine if a resource definition represents a singleton.
13
+ def self.defines_singleton?(definition)
14
+ !definition.key?(:methods) || definition[:methods].empty?
15
+ end
16
+
17
+ # Add a static method to a Class.
18
+ def self.add_static(*args)
19
+ proc do |(name, method), resource|
20
+ resource.class_eval do
21
+ define_singleton_method(name, &method)
22
+ end
23
+ end.curry.call(*args)
24
+ end
25
+
26
+ # Add an instance method to a Class.
27
+ def self.add_method(*args)
28
+ proc do |(name, method), resource|
29
+ resource.class_eval do
30
+ define_method(name, &Helper.forward_self(method))
31
+ end
32
+ end.curry.call(*args)
33
+ end
34
+
35
+ # Add a collection of static methods to a Class.
36
+ def self.add_statics(resource, statics = {})
37
+ return resource if statics.empty?
38
+
39
+ statics.each_with_object(resource, &add_static)
40
+ end
41
+
42
+ # Add a collection of instance methods to a Class.
43
+ def self.add_methods(resource, _request, methods = {})
44
+ return resource if methods.empty?
45
+
46
+ methods.each_with_object(resource, &add_method)
47
+ end
48
+
49
+ # Takes a resource name and creates a class name.
50
+ def self.to_class_name(resource, cid = '')
51
+ parts = resource.to_s.split('-').map(&:capitalize)
52
+
53
+ parts[parts.size - 1] = Inflection.singular(parts.last)
54
+
55
+ name = parts.join ''
56
+
57
+ "#{name}#{cid}"
58
+ end
59
+
60
+ # Create a resource.
61
+ # TODO: copts are not optional
62
+ def self.create(type, request, cid, copts = {})
63
+ resource = Object.const_set(to_class_name(type, cid), Class.new(Base))
64
+ resource.define_singleton_method(:copts) do
65
+ copts
66
+ end
67
+
68
+ resource.define_singleton_method(:type) do
69
+ type
70
+ end
71
+
72
+ resource.define_singleton_method(:request) do
73
+ request
74
+ end
75
+
76
+ resource.define_singleton_method(:cid) do
77
+ cid
78
+ end
79
+
80
+ resource
81
+ end
82
+
83
+ # Create a resource.
84
+ def self._make
85
+ proc do |type, request, cid, options = {}|
86
+ unless Definition::DEFINITION.key? type
87
+ raise ArgumentError, 'Could not find definition for resource: ' \
88
+ "#{type}"
89
+ end
90
+
91
+ definition = Definition::DEFINITION.fetch(type)
92
+
93
+ # Create the resource / class.
94
+ resource = if defines_singleton? definition
95
+ {}
96
+ else
97
+ create(type, request, cid, options)
98
+ end
99
+
100
+ # Add statics.
101
+ if definition.key? Definition::STATICS
102
+ statics = SDK::Static.factory(
103
+ request,
104
+ type,
105
+ definition[Definition::STATICS],
106
+ options
107
+ )
108
+
109
+ add_statics(resource, statics)
110
+ end
111
+
112
+ # Add methods.
113
+ if definition.key? Definition::METHODS
114
+ methods = SDK::Method.factory(
115
+ request,
116
+ type,
117
+ definition[Definition::METHODS],
118
+ options
119
+ )
120
+
121
+ add_methods(resource, request, methods)
122
+ end
123
+
124
+ resource
125
+ end
126
+ end
127
+
128
+ # Generate a memoize key based on factory arguments
129
+ def self.get_memoize_key(resource, _request, cid, _options = {})
130
+ :"#{resource}_#{cid}"
131
+ end
132
+
133
+ # Convenience for get_memoize_key in proc form.
134
+ def self.memoize_key
135
+ proc do |*args|
136
+ get_memoize_key(*args)
137
+ end
138
+ end
139
+
140
+ # TODO: ideal API would be memoize(:make, memoize_key) - in future.
141
+ @make = Polyseerio::Helper.memoize_function(_make, memoize_key)
142
+
143
+ # Memoized calls to make. A little ugly, would like a better memoize API.
144
+ def self.make(*args)
145
+ @make.call(*args)
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,91 @@
1
+ module Polyseerio
2
+ module Resource
3
+ # Helper methods for building and working with resources
4
+ module Helper
5
+ EID_REGEX = Regexp.new('/environments/([\da-z\.-]+)/')
6
+
7
+ # Forward self as first argument. Used for method procs.
8
+ def self.forward_self(func)
9
+ proc do |*args|
10
+ func.call(self, *args)
11
+ end
12
+ end
13
+
14
+ # Given a request path an eid is returned or nil
15
+ def self.get_eid_from_resource_path(path)
16
+ result = EID_REGEX.match path
17
+
18
+ return result if result.nil?
19
+
20
+ result[1]
21
+ end
22
+
23
+ # True if the response is a resource based response
24
+ def self.resource_response?(body)
25
+ body.key?(:data) &&
26
+ (resource?(body[:data]) || resource_collection?(body[:data]))
27
+ end
28
+
29
+ # True if response data is a resource collection (alias)
30
+ def self.resource_collection?(data)
31
+ data.is_a? Array
32
+ end
33
+
34
+ # True if response data is a resource collection (alias)
35
+ def self.resource?(data)
36
+ data.is_a? Hash
37
+ end
38
+
39
+ # Convert parsed response data into an instance
40
+ # TODO: hard to unit-test (due to Factory.make)
41
+ def self.to_instance(data, _meta, _included, cid)
42
+ type = data.fetch(:type, nil)
43
+ id = data.fetch(:id, nil)
44
+ attributes = data.fetch(:attributes, {})
45
+
46
+ attributes[:id] = id
47
+
48
+ # parse_response would only eve be called once the client has been
49
+ # constructed meaning in order to get the class we simply need to
50
+ # pass the type and cid. make is memoized on the type and cid args.
51
+ resource = Factory.make(type, nil, cid)
52
+
53
+ resource.new(attributes) # TODO: need to include meta
54
+ end
55
+
56
+ # Parse a resource response
57
+ # TODO: hard to unit-test (due to Factory.make)
58
+ def self.parse_resource_response(response, cid)
59
+ body = response.body
60
+ meta = body[:meta] || {}
61
+ included = body[:included] || {}
62
+ data = body[:data]
63
+
64
+ eid = get_eid_from_resource_path response.request.uri.path
65
+
66
+ # attach eid if we have attributes and an id
67
+ # would need to occur for each?????
68
+ data[:attributes][:eid] = eid if !eid.nil? && data.key?(:attributes)
69
+
70
+ # if resource collection if so map return
71
+ if resource_collection? data
72
+ return data.map do |item|
73
+ to_instance(item, meta, included, cid)
74
+ end
75
+ end
76
+
77
+ # convert to instance
78
+ to_instance(data, meta, included, cid)
79
+ end
80
+
81
+ # Parse a response
82
+ def self.parse_response(response, cid)
83
+ if resource_response? response.body
84
+ return parse_resource_response(response, cid)
85
+ end
86
+
87
+ response
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,26 @@
1
+ require 'helper'
2
+
3
+ module Polyseerio
4
+ module Resource
5
+ # Reusable resource routines.
6
+ module Routine
7
+ DEFAULT_UPSERT_OPTIONS = {
8
+ key: :name
9
+ }.freeze
10
+
11
+ # Upsert a resource.
12
+ def self.upsert(resource, attributes)
13
+ unless attributes.key? :name
14
+ raise ArgumentError, 'Passed attributes must contain a name.'
15
+ end
16
+
17
+ resource.find_by_name(attributes[:name])
18
+ .then(proc do |reason|
19
+ raise reason if reason.http_code != 404
20
+
21
+ resource.create(attributes).execute.value
22
+ end)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ require 'helper'
2
+ require 'concurrent'
3
+
4
+ module Polyseerio
5
+ # HTTP response wrapper.
6
+ class Response
7
+ def initialize(rest_response)
8
+ @rest_response = rest_response
9
+ end
10
+
11
+ # Returns the response body.
12
+ #
13
+ # NOTE: This function is memoized.
14
+ def body
15
+ @body_result ||= JSON.parse(@rest_response.body, symbolize_names: true)
16
+ end
17
+
18
+ # Returns the original request obect.
19
+ def request
20
+ @rest_response.request
21
+ end
22
+
23
+ private
24
+
25
+ attr_accessor :rest_response
26
+ end
27
+ end