persistence-providers 0.0.3.5 → 0.0.3.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62b3d49ea7a138d6f1f9e99e0b8f776dcc0212ea24e8fba1bc35a2876f466951
4
- data.tar.gz: 4fecccfff86f73b5b9ab5f647294bb5b866b465bfcc2f59c1991722da5cc0b68
3
+ metadata.gz: a18d9fbe5a1507dfde899dc0bf467a6148ae7bda7ed58995854ecc372ef4efa5
4
+ data.tar.gz: 32cf0fa8b1433d55c7f79da8767ed7de1b8d1daa66f8c1e409d6b8978914c938
5
5
  SHA512:
6
- metadata.gz: 7be9867552f0c0cc2cf66cdea3295b6c02c41909d92c645178244b256b4a67079f595ead4a48c91c33a116ba4323498001665ea9e089d68b37941c1618111a7e
7
- data.tar.gz: 7bc22d498ec484b7466853e5ca550554f6567769596417b41f086e515fb58ac20b62b2074638cebee00a7f0c5af396dce8f68684b098374407d673338d6749e7
6
+ metadata.gz: bebb1b072b268c17fff5e2430e37b4fa8dd771cbbdb10930d3e7cf852c008d1d4d49c5f30a5fcce8afa9930da6e06707c9c7bfe3d58f12c13c2101ecf55ec15a
7
+ data.tar.gz: 05126ad2c6f92ab855877e71929cf00f6955e21873b6782a9805c05884ec6e0e08ad53bdb7314589039acef82b96abf8bf376557252314aacefda8359c3c4070
@@ -3,6 +3,7 @@ module DTK::State
3
3
  class Influxdb < self
4
4
  require_relative('influxdb/client')
5
5
  require_relative('influxdb/measurement')
6
+ require_relative('influxdb/semantictype')
6
7
 
7
8
  attr_reader :client, :measurement
8
9
 
@@ -49,7 +50,7 @@ module DTK::State
49
50
  }
50
51
  measurement.write(value_to_write.to_s, required_tags, timestamp)
51
52
  rescue => error
52
- puts error
53
+ fail error
53
54
  end
54
55
  end
55
56
 
@@ -80,7 +81,7 @@ module DTK::State
80
81
  }
81
82
  measurement.write(value_to_write.to_s, required_tags, timestamp)
82
83
  rescue => error
83
- puts error
84
+ fail error
84
85
  end
85
86
  end
86
87
 
@@ -10,8 +10,12 @@ module DTK::State
10
10
  end
11
11
 
12
12
  def query(query_expression)
13
- query_api = self.connection.create_query_api
14
- query_api.query(query_expression)
13
+ begin
14
+ query_api = self.connection.create_query_api
15
+ query_api.query(query_expression)
16
+ rescue => error
17
+ fail "Failed in query"
18
+ end
15
19
  end
16
20
 
17
21
  def write_point(data)
@@ -28,7 +32,7 @@ module DTK::State
28
32
  klass = Measurement.const_get(measurement_name.to_sym.capitalize)
29
33
  klass.new(measurement_name, self)
30
34
  rescue => error
31
- puts error
35
+ fail error
32
36
  end
33
37
  end
34
38
 
@@ -23,7 +23,7 @@ module DTK::State
23
23
  begin
24
24
  check_params_hash(params_hash)
25
25
  flux_query = 'from(bucket:"' + client.connection_parameters[:bucket] + '") |> range(start:-5) |> filter(fn: (r) => r._measurement == "' + name.to_s + '")' + flux_filter(params_hash) + ' |> last()' + '|> drop(columns: ["_start", "_stop", "_field", "_measurement", "attribute_name", "assembly_name", "task_id", "component_name", "namespace"])'
26
- result = self.client.query(flux_query)
26
+ result = self.client.query(query: flux_query)
27
27
  result.values.map(&:records).flatten.map(&:values)
28
28
  rescue => error
29
29
  fail error
@@ -0,0 +1,221 @@
1
+ module DTK::State
2
+ class Component::Attribute::Influxdb
3
+ class SemanticType
4
+ require_relative './client'
5
+ attr_reader :name, :crd_content, :namespace, :client
6
+ attr_accessor :content_to_write
7
+
8
+ def initialize(name, namespace)
9
+ @name = name
10
+ @namespace = namespace
11
+ @client = Client.new
12
+ @crd_content = get(name, namespace)
13
+ @content_to_write = []
14
+ end
15
+
16
+ # no namespace because semantictype instances are going to be unique in cluster
17
+ def get(name, namespace, opts = {})
18
+ begin
19
+ semantictype = ::DTK::CrdClient.get_kubeclient(opts).get_semantictype(name, namespace)
20
+ semantictype.spec[:openAPIV3Schema]
21
+ rescue => error
22
+ fail "SemanticType attribute with name '#{name}' not found on the cluster!. Error: #{error}"
23
+ end
24
+ end
25
+
26
+ def write_semantictype_inventory(inventory, component_id)
27
+ begin
28
+ get_influxdb_properties(inventory)
29
+ content_to_write.each do |point|
30
+ point[:tags].merge!({ component_id: component_id, attribute_name: @name })
31
+ @client.write_point({
32
+ name: point[:name],
33
+ tags: point[:tags],
34
+ fields: point[:fields],
35
+ time: (Time.new.to_f * 1000).to_i
36
+ })
37
+ end
38
+ "Inventory for attribute #{name} written to InfluxDB"
39
+ rescue => error
40
+ fail "#{name} inventory write failed. Error: #{error}"
41
+ end
42
+ end
43
+
44
+ def partial_write_update(component_and_attribute, path, field_name, field_value)
45
+ parent, child = validate_parameter(path)
46
+ component_id, attribute_name = component_and_attribute.split('/')
47
+ # getting previous value for given parameters
48
+ previous_value = { }
49
+ begin
50
+ flux_query = 'from(bucket:"' + @client.connection_parameters[:bucket] + '") |> range(start:-5) |> filter(fn:(r) => r._measurement == "' + attribute_name + "_" + child[:type] + '") |> filter(fn: (r) => r.parent == "' + parent[:name] + '") |> filter(fn: (r) => r.name == "' + child[:name] + '")|> last()'
51
+ result = @client.query(query: flux_query)
52
+ previous_value = result.values.map(&:records).flatten.map(&:values)
53
+ rescue => error
54
+ fail "Partial write could not be completed. Previous point for given parameters not found!"
55
+ end
56
+ update_current(previous_value[0], get_path_to_object(path), field_name, field_value)
57
+ end
58
+
59
+ private
60
+
61
+ def update_current(previous_value, path, field_name, field_value)
62
+ tags = { }
63
+ previous_value.each_pair do |key, value|
64
+ tags[key] = value if key[0..0] != "_" && key != "result" && key != "table"
65
+ end
66
+ fields = Hash.new
67
+ fields[field_name.to_sym] = field_value
68
+ validate_fields(get_partial_definition(path), fields)
69
+ @client.write_point({
70
+ name: previous_value["_measurement"],
71
+ tags: tags,
72
+ fields: fields,
73
+ time: (Time.new.to_f * 1000).to_i
74
+ })
75
+ "Partial write update successful"
76
+ end
77
+
78
+ def get_influxdb_properties(inventory, parent_type = [:top], parent_name = nil)
79
+ content_to_write = []
80
+ properties = { }
81
+ inventory.each_pair do |key, value|
82
+ if value.class.to_s == "Array"
83
+ inventory[key].each do |element|
84
+ get_influxdb_properties(element, parent_type.push(key), inventory[:name])
85
+ end
86
+ else
87
+ properties[key] = value
88
+ end
89
+ end
90
+ resolve_property(parent_type, parent_name, properties)
91
+ parent_type.pop
92
+ "Attribute successfully validated!"
93
+ end
94
+
95
+ def resolve_property(parent_type, parent_name, properties)
96
+ definition = get_partial_definition(parent_type)
97
+ request = get_tags_and_fields(definition, properties)
98
+ validate_request(definition, request)
99
+ request[:name] = name + "_" + parent_type.last.to_s
100
+ request[:tags][:parent] = parent_name unless parent_name.nil?
101
+ content_to_write.push(request)
102
+ end
103
+
104
+ def validate_request(partial_definition, request)
105
+ begin
106
+ validate_tags(partial_definition, request[:tags])
107
+ validate_fields(partial_definition, request[:fields])
108
+ rescue => error
109
+ fail error
110
+ end
111
+ end
112
+
113
+ def get_tags_and_fields(partial_definition, properties)
114
+ tags = { }
115
+ fields = { }
116
+ properties.each_pair do |key, value|
117
+ if partial_definition[key].nil?
118
+ fail "Property '#{key}' not found in the definition of attribute"
119
+ else
120
+ if partial_definition[key][:metric].nil? || partial_definition[key][:metric] == false
121
+ tags[key] = value
122
+ else
123
+ fields[key] = value
124
+ end
125
+ end
126
+ end
127
+ {
128
+ tags: tags,
129
+ fields: fields
130
+ }
131
+ end
132
+
133
+ def validate_fields(partial_definition, fields)
134
+
135
+ partial_definition.each_pair do |key, value|
136
+ next if key == :required || value[:metric] == (false || nil)
137
+
138
+ if fields[key].nil?
139
+ fail "Field #{key} is missing. Validation of request failed!"
140
+ elsif value[:type].capitalize != fields[key].class.to_s
141
+ fail "Defined type for SemanticType attribute property '#{key}' is #{value[:type].capitalize}, #{fields[key].class} provided"
142
+ end
143
+ end
144
+ end
145
+
146
+ def validate_tags(partial_definition, tags)
147
+ partial_definition.each_pair do |key, value|
148
+ next if key == :required || value[:metric] == true
149
+
150
+ if tags[key].nil?
151
+ if value[:default].nil?
152
+ fail "Property #{key} is missing. Validation of request failed!"
153
+ else
154
+ tags[key] = value[:default]
155
+ end
156
+ else
157
+ type = tags[key].class
158
+ type = "Boolean" if type == TrueClass || type == FalseClass
159
+ if value[:type].capitalize == type.to_s
160
+ next
161
+ else
162
+ fail "Defined type for SemanticType attribute property '#{key}' is #{value[:type].capitalize}, #{type} provided"
163
+ end
164
+ end
165
+ end
166
+ end
167
+
168
+ def get_partial_definition(path)
169
+ i = 0
170
+ definition = { }
171
+ semantictype_crd = crd_content[:properties]
172
+ while i < path.length
173
+ if path[i].to_sym == :top
174
+ semantictype_crd.each_pair do |key, value|
175
+ if key == :required
176
+ definition[key] = value
177
+ else
178
+ definition[key] = value if value[:type] != "array"
179
+ end
180
+ end
181
+ else
182
+ definition = {}
183
+ definition[:required] = semantictype_crd[path[i].to_sym][:items][:required]
184
+ semantictype_crd[path[i].to_sym][:items][:properties].each_pair do |key, value|
185
+ definition[key] = value if value[:type] != "array"
186
+ end
187
+ semantictype_crd = semantictype_crd[path[i].to_sym][:items][:properties]
188
+ end
189
+ i+=1
190
+ end
191
+ definition
192
+ end
193
+
194
+ def get_path_to_object(parameter)
195
+ path = ["top"]
196
+ array = parameter.split('/')
197
+ array.each do |element|
198
+ path.push(element.split(':')[1])
199
+ end
200
+ path
201
+ end
202
+
203
+ def validate_parameter(parameter)
204
+ array_of_parameters = []
205
+ begin
206
+ parameter.split('/').each_with_index do |param, index|
207
+ name, type = param.split(':')
208
+ fail unless name && type
209
+ array_of_parameters.push({
210
+ name: name,
211
+ type: type
212
+ })
213
+ end
214
+ array_of_parameters
215
+ rescue => error
216
+ fail "Could not resolve parameter '#{parameter}'. It should be in format: 'parent:type/child:type'"
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'persistence-providers'
3
- spec.version = '0.0.3.5'
3
+ spec.version = '0.0.3.6'
4
4
  spec.author = 'Reactor8'
5
5
  spec.email = 'support@reactor8.com'
6
6
  spec.description = %q{Persistence providers plugin}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: persistence-providers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.5
4
+ version: 0.0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reactor8
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-12 00:00:00.000000000 Z
11
+ date: 2020-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kubeclient
@@ -70,6 +70,7 @@ files:
70
70
  - lib/state/component/providers/influxdb/measurement/errors.rb
71
71
  - lib/state/component/providers/influxdb/measurement/events.rb
72
72
  - lib/state/component/providers/influxdb/measurement/states.rb
73
+ - lib/state/component/providers/influxdb/semantictype.rb
73
74
  - lib/state/component/providers/kube_crd.rb
74
75
  - lib/state/component_def.rb
75
76
  - lib/state/component_def/attribute_type_info.rb