persistence-providers 0.0.3.6 → 0.0.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a18d9fbe5a1507dfde899dc0bf467a6148ae7bda7ed58995854ecc372ef4efa5
4
- data.tar.gz: 32cf0fa8b1433d55c7f79da8767ed7de1b8d1daa66f8c1e409d6b8978914c938
3
+ metadata.gz: c0df9c5f3778b1aba3a4b2474b9e47dad64d60566697c3ee15708e26a1a8bfe6
4
+ data.tar.gz: a7d39896b337a3579c491b4f13553b28556324b6ecbfdaf7439eafe1f2f6d6b7
5
5
  SHA512:
6
- metadata.gz: bebb1b072b268c17fff5e2430e37b4fa8dd771cbbdb10930d3e7cf852c008d1d4d49c5f30a5fcce8afa9930da6e06707c9c7bfe3d58f12c13c2101ecf55ec15a
7
- data.tar.gz: 05126ad2c6f92ab855877e71929cf00f6955e21873b6782a9805c05884ec6e0e08ad53bdb7314589039acef82b96abf8bf376557252314aacefda8359c3c4070
6
+ metadata.gz: 55e280a54d5a75f1bc6ae12b5fcf31659bae2efcf7c83897c0a6fed78d576464173fecec7bc2807945caf56cc3c930248947fd3d747c934ba75e06d73762715a
7
+ data.tar.gz: 3e8f981dd1ca1cbb000f1e926bebee66bb73eeaf710c4f0824154dae1526dd74d7dc2c1a87f40e9a58a94ba48fa9ca39ad054f5c9cbc4d3338c0340ba7283931
@@ -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
- ::DTK::CrdClient.instance.kubeclient
21
+ kubeclient_version(opts)
16
22
  end
17
23
  end
18
24
 
19
- # opts can have keys
20
- # kubernetes_client - already instantiated kubernetes client
21
- def initialize(opts = {})
22
- if @kubeclient = opts[:kubernetes_client]
23
- return @kubeclient
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
- 'dtk.io/v1alpha1',
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
@@ -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.components.find{ |cmp| cmp.to_hash.keys.first.to_s == component_name }
21
- Component.new(component_name, matching_component[component_name], crd_assembly, opts)
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
- @content[:attributes].each do |name, content|
50
- attribute_with_values << { name => content[:value] }
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
- errors = client.measurement_helper(:errors)
19
- required_tags.merge!({ correlator_type: opts[:entrypoint].split("/").last.split(".")[0] })
20
- errors.get_last_point(required_tags)
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
- if opts[:provider] == "correlation"
29
- errors = client.measurement_helper(:errors)
30
- required_tags = get_required_tags(namespace, component_name, assembly_name, attribute_name)
31
- required_tags.merge!({ correlator_type: opts[:entrypoint].split("/").last.split(".")[0] })
32
- errors.write(value.to_s, required_tags, timestamp)
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
- begin
41
- fail "Bad timestamp input, write operation wont be completed" if timestamp > Time.new
42
- value_to_write = { event_source: event_source, event_message: event_message }
43
- required_tags = {
44
- event_id: event_id,
45
- pod_name: pod_name,
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
- begin
71
- fail "Bad timestamp input, write operation wont be completed" if timestamp > Time.new
72
- value_to_write = { spec: spec, status: status }
73
- required_tags = {
74
- type: type,
75
- name: name,
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 get_required_tags(namespace, component_name, assembly_name, attribute_name)
91
- required_tags = {
92
- namespace: namespace,
93
- component_name: component_name,
94
- assembly_name: assembly_name,
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
- 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
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
- begin
23
- write_api = self.connection.create_write_api
24
- write_api.write(data: data)
25
- rescue => error
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
- begin
32
- klass = Measurement.const_get(measurement_name.to_sym.capitalize)
33
- klass.new(measurement_name, self)
34
- rescue => error
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
- begin
60
- InfluxDB2::Client.new(connection_parameters[:url], connection_parameters[:token],
61
- bucket: connection_parameters[:bucket],
62
- org: connection_parameters[:org],
63
- precision: InfluxDB2::WritePrecision::MILLISECOND,
64
- use_ssl: false)
65
- rescue => error
66
- fail "Error: #{error}"
67
- end
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
- begin
24
- check_params_hash(params_hash)
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(query: flux_query)
27
- result.values.map(&:records).flatten.map(&:values)
28
- rescue => error
29
- fail error
30
- end
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