persistence-providers 0.0.3.6 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/crd_client.rb +24 -9
- data/lib/persistence_providers.rb +2 -0
- data/lib/state/component.rb +94 -5
- data/lib/state/component/providers/influxdb.rb +31 -67
- data/lib/state/component/providers/influxdb/client.rb +24 -27
- data/lib/state/component/providers/influxdb/measurement.rb +17 -9
- data/lib/state/component/providers/influxdb/measurement/attribute_measurement.rb +2 -4
- data/lib/state/component/providers/influxdb/measurement/errors.rb +9 -4
- data/lib/state/component/providers/influxdb/measurement/events.rb +14 -4
- data/lib/state/component/providers/influxdb/measurement/states.rb +15 -4
- data/lib/state/component/providers/influxdb/semantictype.rb +98 -74
- data/lib/state/component_def.rb +4 -1
- data/lib/state/component_def/attribute_type_info.rb +13 -0
- data/lib/state/crd_assembly.rb +59 -7
- data/lib/state/workflow.rb +26 -0
- data/lib/state/workflow_instance.rb +138 -8
- data/lib/state/workflow_instance/attribute_type_info.rb +13 -0
- data/lib/utils.rb +5 -0
- data/lib/utils/log.rb +22 -0
- data/persistence-providers.gemspec +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0df9c5f3778b1aba3a4b2474b9e47dad64d60566697c3ee15708e26a1a8bfe6
|
4
|
+
data.tar.gz: a7d39896b337a3579c491b4f13553b28556324b6ecbfdaf7439eafe1f2f6d6b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55e280a54d5a75f1bc6ae12b5fcf31659bae2efcf7c83897c0a6fed78d576464173fecec7bc2807945caf56cc3c930248947fd3d747c934ba75e06d73762715a
|
7
|
+
data.tar.gz: 3e8f981dd1ca1cbb000f1e926bebee66bb73eeaf710c4f0824154dae1526dd74d7dc2c1a87f40e9a58a94ba48fa9ca39ad054f5c9cbc4d3338c0340ba7283931
|
data/lib/crd_client.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
require 'kubeclient'
|
2
2
|
require 'celluloid/io'
|
3
|
-
require 'singleton'
|
3
|
+
# require 'singleton'
|
4
4
|
|
5
5
|
module DTK
|
6
6
|
class CrdClient
|
7
|
-
include Singleton
|
7
|
+
# include Singleton
|
8
|
+
DEFAULT_API_VERSION = 'v1alpha1'
|
9
|
+
|
10
|
+
# COMPONENT_DEF_CRD_VERSION = ENV["COMPONENT_DEF_CRD_VERSION"]
|
11
|
+
# ASSEMBLY_CRD_VERSION = ENV["ASSEMBLY_CRD_VERSION"]
|
12
|
+
# WORKFLOW_CRD_VERSION = ENV["WORKFLOW_CRD_VERSION"]
|
13
|
+
# WORKFLOW_INSTANCE_CRD_VERSION = ENV["WORKFLOW_INSTANCE_CRD_VERSION"]
|
8
14
|
|
9
15
|
attr_accessor :kubeclient
|
10
16
|
|
@@ -12,17 +18,26 @@ module DTK
|
|
12
18
|
if @kubeclient = opts[:kubeclient]
|
13
19
|
@kubeclient
|
14
20
|
else
|
15
|
-
|
21
|
+
kubeclient_version(opts)
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if
|
23
|
-
return
|
25
|
+
def self.kubeclient_version(opts = {})
|
26
|
+
version = opts[:apiVersion] || DEFAULT_API_VERSION
|
27
|
+
|
28
|
+
if existing_version = KubeclientVersions[version]
|
29
|
+
return existing_version
|
30
|
+
else
|
31
|
+
new_instance = new(version).kubeclient
|
32
|
+
KubeclientVersions[version] = new_instance
|
33
|
+
new_instance
|
24
34
|
end
|
35
|
+
end
|
36
|
+
KubeclientVersions = {}
|
25
37
|
|
38
|
+
# opts can have keys
|
39
|
+
# kubernetes_client - already instantiated kubernetes client
|
40
|
+
def initialize(apiVersion)
|
26
41
|
ssl_options = {}
|
27
42
|
auth_options = { bearer_token_file: '/var/run/secrets/kubernetes.io/serviceaccount/token' }
|
28
43
|
|
@@ -37,7 +52,7 @@ module DTK
|
|
37
52
|
|
38
53
|
@kubeclient = Kubeclient::Client.new(
|
39
54
|
'https://kubernetes.default.svc/apis/',
|
40
|
-
|
55
|
+
"dtk.io/#{apiVersion}",
|
41
56
|
auth_options: auth_options,
|
42
57
|
ssl_options: ssl_options,
|
43
58
|
socket_options: socket_options
|
@@ -1,10 +1,12 @@
|
|
1
1
|
module DTK
|
2
2
|
module State
|
3
|
+
require_relative 'utils'
|
3
4
|
require_relative 'crd_client'
|
4
5
|
require_relative 'state/crd_assembly'
|
5
6
|
require_relative 'state/component'
|
6
7
|
require_relative 'state/component_def'
|
7
8
|
require_relative 'state/executable_action'
|
8
9
|
require_relative 'state/workflow_instance'
|
10
|
+
require_relative 'state/workflow'
|
9
11
|
end
|
10
12
|
end
|
data/lib/state/component.rb
CHANGED
@@ -3,12 +3,14 @@ module DTK::State
|
|
3
3
|
require_relative 'component/attribute'
|
4
4
|
|
5
5
|
attr_reader :name, :parent, :component_def
|
6
|
+
attr_accessor :raw_attributes
|
6
7
|
|
7
8
|
def initialize(name, component_content, parent, opts = {})
|
8
9
|
@name = name
|
9
10
|
# @parent = parent
|
10
11
|
@component_defs = parent.references.component_def
|
11
12
|
@component_def = get_component_def(opts)
|
13
|
+
@raw_attributes = component_content[:attributes] || {}
|
12
14
|
|
13
15
|
@attribute_objs = Attribute.create_from_kube_hash(component_content[:attributes] || {})# convert_to_attribute_objects(component_content[:attributes])
|
14
16
|
end
|
@@ -17,11 +19,50 @@ module DTK::State
|
|
17
19
|
# task_id
|
18
20
|
def self.get(crd_assembly_namespace, crd_assembly_name, component_name, opts = {})
|
19
21
|
crd_assembly = CrdAssembly.get(crd_assembly_namespace, crd_assembly_name, opts)
|
20
|
-
if matching_component = crd_assembly
|
21
|
-
Component.new(component_name, matching_component
|
22
|
+
if matching_component = Component.find_matching_component(crd_assembly, component_name)
|
23
|
+
Component.new(component_name, Component.get_component_content(matching_component, component_name), crd_assembly, opts)
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
27
|
+
def self.get_with_influx_data(namespace, assembly_name, component_name, opts = {})
|
28
|
+
component = get(namespace, assembly_name, component_name, opts)
|
29
|
+
return unless component
|
30
|
+
attributes = component.raw_attributes.to_hash
|
31
|
+
|
32
|
+
attr_type_info = component.component_def.attribute_type_info
|
33
|
+
attr_type_info.each do |attr_info|
|
34
|
+
if attr_info.temporal
|
35
|
+
attribute_name = attr_info.name.to_sym
|
36
|
+
influxdb = ::DTK::State::Component::Attribute::Influxdb.new(:attributes)
|
37
|
+
influxdb_attribute = influxdb.get(namespace, component_name, assembly_name, attribute_name, opts)
|
38
|
+
if valid_attribute = influxdb_attribute.first
|
39
|
+
value = valid_attribute['_value']
|
40
|
+
if attributes[attribute_name]
|
41
|
+
if attributes[attribute_name].is_a?(String)
|
42
|
+
attributes[attribute_name] = value
|
43
|
+
else
|
44
|
+
attributes[attribute_name][:value] = value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
component.raw_attributes = attributes
|
52
|
+
component
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_hash
|
56
|
+
{
|
57
|
+
name: @name,
|
58
|
+
component_def: {
|
59
|
+
name: @component_def.name,
|
60
|
+
namespace: @component_def.namespace
|
61
|
+
},
|
62
|
+
attributes: @raw_attributes.to_hash
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
25
66
|
# opts can have keys
|
26
67
|
# task_id
|
27
68
|
# format:
|
@@ -44,16 +85,64 @@ module DTK::State
|
|
44
85
|
end
|
45
86
|
end
|
46
87
|
|
88
|
+
def attribute_metadata
|
89
|
+
attributes = @raw_attributes.to_hash
|
90
|
+
attr_type_info = @component_def.attribute_type_info
|
91
|
+
attribute_metadata = {}
|
92
|
+
|
93
|
+
attr_type_info.each do |attr_info|
|
94
|
+
attr_info_hash = attr_info.to_hash
|
95
|
+
attribute_name = attr_info_hash[:name].to_sym
|
96
|
+
|
97
|
+
if attribute = attributes[attribute_name]
|
98
|
+
if attribute.is_a?(String)
|
99
|
+
attribute = { value: attribute }
|
100
|
+
end
|
101
|
+
|
102
|
+
attribute_metadata[attribute_name] = attr_info_hash.merge(attribute)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
attribute_metadata
|
107
|
+
end
|
108
|
+
|
47
109
|
def attribute_values
|
48
|
-
attribute_with_values =
|
49
|
-
@
|
50
|
-
attribute_with_values
|
110
|
+
attribute_with_values = {}
|
111
|
+
@raw_attributes.each do |name, content|
|
112
|
+
attribute_with_values.merge!(name => content[:value])
|
51
113
|
end
|
52
114
|
attribute_with_values
|
53
115
|
end
|
54
116
|
|
117
|
+
def self.create_from_kube_array(kube_components, crd_assembly)
|
118
|
+
kube_components.map do |component_hash|
|
119
|
+
if component_hash.is_a?(String)
|
120
|
+
component_name = component_hash
|
121
|
+
component_content = {}
|
122
|
+
else
|
123
|
+
component_name = component_hash.to_hash.keys.first
|
124
|
+
component_content = component_hash[component_name]
|
125
|
+
end
|
126
|
+
Component.new(component_name, component_content, crd_assembly)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
55
130
|
private
|
56
131
|
|
132
|
+
def self.get_component_content(matching_component, component_name)
|
133
|
+
return matching_component.is_a?(String) ? {} : matching_component[component_name]
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.find_matching_component(assembly, component_name)
|
137
|
+
assembly.components.find do |cmp|
|
138
|
+
if cmp.is_a? String
|
139
|
+
cmp == component_name
|
140
|
+
else
|
141
|
+
cmp.to_hash.keys.first.to_s == component_name
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
57
146
|
def get_component_def(opts = {})
|
58
147
|
destructured_component = destructure_component_full_name
|
59
148
|
component_def = @component_defs.find { |component_def| component_def[:name] == destructured_component[:component_def_name] }
|
@@ -4,6 +4,7 @@ module DTK::State
|
|
4
4
|
require_relative('influxdb/client')
|
5
5
|
require_relative('influxdb/measurement')
|
6
6
|
require_relative('influxdb/semantictype')
|
7
|
+
require_relative('../../../utils/log')
|
7
8
|
|
8
9
|
attr_reader :client, :measurement
|
9
10
|
|
@@ -13,88 +14,51 @@ module DTK::State
|
|
13
14
|
end
|
14
15
|
|
15
16
|
def get(namespace, component_name, assembly_name, attribute_name, opts = {})
|
16
|
-
required_tags = get_required_tags(namespace, component_name, assembly_name, attribute_name)
|
17
|
-
if opts[:provider] == "correlation"
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
elsif
|
22
|
-
last_value = measurement.get_last_point(required_tags)
|
23
|
-
last_value
|
24
|
-
end
|
17
|
+
required_tags = measurement.get_required_tags(namespace, component_name, assembly_name, attribute_name)
|
18
|
+
required_tags.merge! measurement.get_correlator_type(opts[:entrypoint]) if opts[:provider] == "correlation"
|
19
|
+
measurement.get_last_point(required_tags)
|
20
|
+
rescue => e
|
21
|
+
raise "Error happened while getting attribute from InfluxDB.\nError: #{e}"
|
25
22
|
end
|
26
23
|
|
27
24
|
def write(namespace, component_name, assembly_name, attribute_name, value, opts = {}, timestamp = nil)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
elsif
|
34
|
-
required_tags = get_required_tags(namespace, component_name, assembly_name, attribute_name)
|
35
|
-
measurement.write(value, required_tags, timestamp)
|
36
|
-
end
|
25
|
+
required_tags = measurement.get_required_tags(namespace, component_name, assembly_name, attribute_name)
|
26
|
+
required_tags.merge! measurement.get_correlator_type(opts[:entrypoint]) if opts[:provider] == "correlation"
|
27
|
+
measurement.write(value.to_s, required_tags, timestamp)
|
28
|
+
rescue => e
|
29
|
+
raise "Error happened while writing attribute into InfluxDB.\Error: #{e}"
|
37
30
|
end
|
38
31
|
|
39
32
|
def write_event(event_id, pod_name, pod_namespace, event_source, event_message, component_name, attribute_name, task_id, timestamp)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
pod_namespace: pod_namespace,
|
47
|
-
component_name: component_name,
|
48
|
-
attribute_name: attribute_name,
|
49
|
-
task_id: task_id
|
50
|
-
}
|
51
|
-
measurement.write(value_to_write.to_s, required_tags, timestamp)
|
52
|
-
rescue => error
|
53
|
-
fail error
|
54
|
-
end
|
33
|
+
fail "Bad timestamp input, write operation wont be completed" if timestamp > Time.new
|
34
|
+
value_to_write = { event_source: event_source, event_message: event_message }
|
35
|
+
required_tags = measurement.get_required_tags(event_id, pod_name, pod_namespace, component_name, attribute_name, task_id)
|
36
|
+
measurement.write(value_to_write.to_s, required_tags, timestamp)
|
37
|
+
rescue => error
|
38
|
+
raise "Error happened while writing event into InfluxDB.\nError: #{e}"
|
55
39
|
end
|
56
40
|
|
57
41
|
def get_event(event_id, pod_name, pod_namespace, component_name, attribute_name, task_id)
|
58
|
-
required_tags =
|
59
|
-
event_id: event_id,
|
60
|
-
pod_name: pod_name,
|
61
|
-
pod_namespace: pod_namespace,
|
62
|
-
component_name: component_name,
|
63
|
-
attribute_name: attribute_name,
|
64
|
-
task_id: task_id
|
65
|
-
}
|
42
|
+
required_tags = measurement.get_required_tags(event_id, pod_name, pod_namespace, component_name, attribute_name, task_id)
|
66
43
|
last_point = measurement.get_last_point(required_tags)
|
44
|
+
rescue => e
|
45
|
+
raise "Error happened while getting event from InfluxDB.\nError: #{e}"
|
67
46
|
end
|
68
47
|
|
69
48
|
def write_state(type, name, namespace, object_state, spec, status, component_name, attribute_name, task_id, timestamp)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
namespace: namespace,
|
77
|
-
object_state: object_state,
|
78
|
-
component_name: component_name,
|
79
|
-
attribute_name: attribute_name,
|
80
|
-
task_id: task_id
|
81
|
-
}
|
82
|
-
measurement.write(value_to_write.to_s, required_tags, timestamp)
|
83
|
-
rescue => error
|
84
|
-
fail error
|
85
|
-
end
|
49
|
+
raise "Bad timestamp input, write operation to InfluxDB wont be completed" if timestamp > Time.new
|
50
|
+
value_to_write = { spec: spec, status: status }
|
51
|
+
required_tags = measurement.get_required_tags(type, name, namespace, object_state, component_name, attribute_name, task_id)
|
52
|
+
measurement.write(value_to_write.to_s, required_tags, timestamp)
|
53
|
+
rescue => e
|
54
|
+
raise "Error happened while writing state into InfluxDB.\nError: #{e}"
|
86
55
|
end
|
87
|
-
|
88
|
-
private
|
89
56
|
|
90
|
-
def
|
91
|
-
required_tags =
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
attribute_name: attribute_name,
|
96
|
-
task_id: "1"
|
97
|
-
}
|
57
|
+
def get_state(type, name, namespace, object_state, component_name, attribute_name, task_id)
|
58
|
+
required_tags = measurement.get_required_tags(type, name, namespace, object_state, component_name, attribute_name, task_id)
|
59
|
+
measurement.get_last_point(required_tags)
|
60
|
+
rescue => e
|
61
|
+
raise "Error happened while getting state from InfluxDB.\nError: #{e}"
|
98
62
|
end
|
99
63
|
end
|
100
64
|
end
|
@@ -10,30 +10,24 @@ module DTK::State
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def query(query_expression)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
fail "Failed in query"
|
18
|
-
end
|
13
|
+
query_api = self.connection.create_query_api
|
14
|
+
query_api.query(query_expression)
|
15
|
+
rescue => e
|
16
|
+
raise "Failed while processing flux query!. Error: #{e}"
|
19
17
|
end
|
20
18
|
|
21
19
|
def write_point(data)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
fail error
|
27
|
-
end
|
20
|
+
write_api = self.connection.create_write_api
|
21
|
+
write_api.write(data: data)
|
22
|
+
rescue => e
|
23
|
+
raise e
|
28
24
|
end
|
29
25
|
|
30
26
|
def measurement_helper(measurement_name)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
fail error
|
36
|
-
end
|
27
|
+
klass = Measurement.const_get(measurement_name.to_sym.capitalize)
|
28
|
+
klass.new(measurement_name, self)
|
29
|
+
rescue => e
|
30
|
+
raise e
|
37
31
|
end
|
38
32
|
|
39
33
|
attr_reader :connection_parameters, :connection
|
@@ -53,18 +47,21 @@ module DTK::State
|
|
53
47
|
org: params[:org],
|
54
48
|
bucket: params[:bucket]
|
55
49
|
}
|
50
|
+
rescue => e
|
51
|
+
raise "Problem happened while processing InfluxDB connection parameters. Error: #{e}"
|
56
52
|
end
|
57
53
|
|
58
54
|
def return_connection(connection_parameters)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
55
|
+
client = InfluxDB2::Client.new(connection_parameters[:url], connection_parameters[:token],
|
56
|
+
bucket: connection_parameters[:bucket],
|
57
|
+
org: connection_parameters[:org],
|
58
|
+
precision: InfluxDB2::WritePrecision::MILLISECOND,
|
59
|
+
use_ssl: false)
|
60
|
+
query_api = client.create_query_api
|
61
|
+
query_api.query(query: 'from(bucket:"' + connection_parameters[:bucket] + '") |> range(start: -5)')
|
62
|
+
client
|
63
|
+
rescue => e
|
64
|
+
raise "Connection with InfluxDB could not be established. #{e}"
|
68
65
|
end
|
69
66
|
end
|
70
67
|
end
|
@@ -20,14 +20,22 @@ module DTK::State
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def get_last_point(params_hash = {})
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
23
|
+
check_params_hash(params_hash)
|
24
|
+
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"])'
|
25
|
+
result = self.client.query(query: flux_query)
|
26
|
+
result.values.map(&:records).flatten.map(&:values)
|
27
|
+
rescue => e
|
28
|
+
raise "Failed while getting last attribute point. Error: #{e}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_required_tags(namespace, component_name, assembly_name, attribute_name)
|
32
|
+
required_tags = {
|
33
|
+
namespace: namespace,
|
34
|
+
component_name: component_name,
|
35
|
+
assembly_name: assembly_name,
|
36
|
+
attribute_name: attribute_name,
|
37
|
+
task_id: "1"
|
38
|
+
}
|
31
39
|
end
|
32
40
|
|
33
41
|
protected
|
@@ -90,7 +98,7 @@ module DTK::State
|
|
90
98
|
fail "Parameter '#{name}' has an illegal type, legal types are #{LEGAL_TAG_CLASSES.join(', ')}"
|
91
99
|
end
|
92
100
|
end
|
93
|
-
|
101
|
+
|
94
102
|
end
|
95
103
|
end
|
96
104
|
end
|