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 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