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 +4 -4
- data/lib/state/component/providers/influxdb.rb +3 -2
- data/lib/state/component/providers/influxdb/client.rb +7 -3
- data/lib/state/component/providers/influxdb/measurement.rb +1 -1
- data/lib/state/component/providers/influxdb/semantictype.rb +221 -0
- data/persistence-providers.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a18d9fbe5a1507dfde899dc0bf467a6148ae7bda7ed58995854ecc372ef4efa5
|
4
|
+
data.tar.gz: 32cf0fa8b1433d55c7f79da8767ed7de1b8d1daa66f8c1e409d6b8978914c938
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
|
-
|
14
|
-
|
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
|
-
|
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
|
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.
|
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-
|
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
|