persistence-providers 0.0.4.1 → 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: 9bc555b9367087540ccddc49bc1ce3fa937b0a36be7b3d6ff832373a9beeadd0
4
- data.tar.gz: 5ae84500a46b183544d53b1d7d2f90cf6b49bcf52d34d2b95eba8474f7653c93
3
+ metadata.gz: c0df9c5f3778b1aba3a4b2474b9e47dad64d60566697c3ee15708e26a1a8bfe6
4
+ data.tar.gz: a7d39896b337a3579c491b4f13553b28556324b6ecbfdaf7439eafe1f2f6d6b7
5
5
  SHA512:
6
- metadata.gz: 52cc878735fdf04cb19b7a202ff2622872b4514f40c1b849a0ff73a821f4e8e333c1aa9a3ac6ba6b31de29b199f4c49fb5fbd3df2c2bdf64fd4d421f6ff67e7d
7
- data.tar.gz: a9b7fbf25e02a5b1dc15220760e91ca1bc703e7f1c2f388f6f2b083c48170c1162ffc483464cbde99f31e2465dd687c78bc47006a5ad9ee6157c5c40538083e9
6
+ metadata.gz: 55e280a54d5a75f1bc6ae12b5fcf31659bae2efcf7c83897c0a6fed78d576464173fecec7bc2807945caf56cc3c930248947fd3d747c934ba75e06d73762715a
7
+ data.tar.gz: 3e8f981dd1ca1cbb000f1e926bebee66bb73eeaf710c4f0824154dae1526dd74d7dc2c1a87f40e9a58a94ba48fa9ca39ad054f5c9cbc4d3338c0340ba7283931
@@ -7,5 +7,6 @@ module DTK
7
7
  require_relative 'state/component_def'
8
8
  require_relative 'state/executable_action'
9
9
  require_relative 'state/workflow_instance'
10
+ require_relative 'state/workflow'
10
11
  end
11
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
@@ -22,6 +24,45 @@ module DTK::State
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,14 +85,48 @@ 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
 
57
132
  def self.get_component_content(matching_component, component_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
 
@@ -2,7 +2,6 @@ module DTK::State
2
2
  class Component::Attribute::Influxdb
3
3
  class Measurement
4
4
  class Attributes < self
5
-
6
5
  def write(value, params_hash = {}, timestamp)
7
6
  checked_params_hash = check_params_hash(params_hash)
8
7
  write_point(value, checked_params_hash, timestamp)
@@ -11,10 +10,9 @@ module DTK::State
11
10
  protected
12
11
 
13
12
  def required_params
14
- [:namespace, :component_name, :assembly_name, :attribute_name, :task_id]
13
+ %i[namespace component_name assembly_name attribute_name task_id]
15
14
  end
16
-
17
- end
15
+ end
18
16
  end
19
17
  end
20
18
  end
@@ -9,18 +9,17 @@ module DTK::State
9
9
  end
10
10
 
11
11
  def get_correlator_type(entrypoint)
12
- {
13
- correlator_type: entrypoint.split("/").last.split(".")[0]
12
+ {
13
+ correlator_type: entrypoint.split('/').last.split('.')[0]
14
14
  }
15
15
  end
16
16
 
17
17
  protected
18
18
 
19
19
  def required_params
20
- [:namespace, :component_name, :assembly_name, :task_id, :attribute_name, :task_id, :correlator_type]
20
+ %i[namespace component_name assembly_name task_id attribute_name correlator_type]
21
21
  end
22
-
23
- end
22
+ end
24
23
  end
25
24
  end
26
- end
25
+ end
@@ -22,10 +22,9 @@ module DTK::State
22
22
  protected
23
23
 
24
24
  def required_params
25
- [:event_id, :pod_name, :pod_namespace, :component_name, :attribute_name, :task_id]
25
+ %i[event_id pod_name pod_namespace component_name attribute_name task_id]
26
26
  end
27
-
28
- end
27
+ end
29
28
  end
30
29
  end
31
- end
30
+ end
@@ -23,10 +23,9 @@ module DTK::State
23
23
  protected
24
24
 
25
25
  def required_params
26
- [:type, :name, :namespace, :object_state, :component_name, :attribute_name, :task_id]
26
+ %i[type name namespace object_state component_name attribute_name task_id]
27
27
  end
28
-
29
- end
28
+ end
30
29
  end
31
30
  end
32
- end
31
+ end
@@ -2,7 +2,8 @@ module DTK::State
2
2
  class Component::Attribute::Influxdb
3
3
  class SemanticType
4
4
  require_relative './client'
5
- attr_reader :name, :crd_content, :namespace, :client
5
+ require_relative('../../../../utils/log')
6
+ attr_reader :name, :crd_content, :namespace, :client, :expanded_semantictype_spec
6
7
  attr_accessor :content_to_write
7
8
 
8
9
  def initialize(name, namespace)
@@ -11,75 +12,103 @@ module DTK::State
11
12
  @client = Client.new
12
13
  @crd_content = get(name, namespace)
13
14
  @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
15
+ @expanded_spec = ::DTK::CrdClient.get_kubeclient({}).get_semantictype(name, namespace).expandedSpec
16
+ @expanded_semantictype_spec = expand(crd_content.to_h[:properties], @expanded_spec)
24
17
  end
25
18
 
26
19
  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}"
20
+ get_influxdb_properties(inventory)
21
+ content_to_write.each do |point|
22
+ point[:tags].merge!({ component_id: component_id, attribute_name: @name })
23
+ @client.write_point({
24
+ name: point[:name],
25
+ tags: point[:tags],
26
+ fields: point[:fields],
27
+ time: (Time.new.to_f * 1000).to_i
28
+ })
41
29
  end
30
+ rescue => e
31
+ raise "#{name} inventory write failed. Error: #{e}"
42
32
  end
43
33
 
44
34
  def partial_write_update(component_and_attribute, path, field_name, field_value)
45
35
  parent, child = validate_parameter(path)
46
36
  component_id, attribute_name = component_and_attribute.split('/')
47
37
  # getting previous value for given parameters
48
- previous_value = { }
38
+ previous_value = {}
49
39
  begin
50
40
  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
41
  result = @client.query(query: flux_query)
52
42
  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!"
43
+ rescue => e
44
+ raise "Partial write could not be completed. Previous point for given parameters not found!. Error: #{e}"
55
45
  end
56
46
  update_current(previous_value[0], get_path_to_object(path), field_name, field_value)
57
47
  end
58
48
 
59
49
  private
60
50
 
51
+ def expand(crd_content, expanded_spec)
52
+ if expanded_spec.nil?
53
+ expanded_spec = {}
54
+ populate_semantictypes(crd_content, expanded_spec)
55
+ ::DTK::CrdClient.get_kubeclient({}).merge_patch_semantictype(name, { expandedSpec: expanded_spec }, namespace)
56
+ end
57
+ expanded_spec
58
+ end
59
+
60
+ def get(name, namespace, opts = {})
61
+ semantictype = ::DTK::CrdClient.get_kubeclient(opts).get_semantictype(name, namespace)
62
+ semantictype.spec[:openAPIV3Schema]
63
+ rescue => e
64
+ raise "SemanticType attribute with name '#{name}' not found on the cluster!. Error: #{e.inspect}"
65
+ end
66
+
67
+ def populate_semantictypes(crd, expanded_spec, parent = nil)
68
+ crd.each_pair do |key, value|
69
+ basic, semantictype = value[:type].split(':')
70
+ if semantictype
71
+ expanded_spec[key] = get(basic.to_s, namespace).to_h[:properties]
72
+ crd[key] = get(basic.to_s, namespace).to_h[:properties]
73
+ temporary_expanded_spec = populate_semantictypes(crd[key], expanded_spec[key], basic)
74
+ end
75
+ if basic == 'array'
76
+ basic, semantictype = value[:items][:type].split(':')
77
+ if semantictype
78
+ expanded_spec[key] = get(basic.to_s, namespace).to_h[:properties]
79
+ crd[key] = get(basic.to_s, namespace).to_h[:properties]
80
+ temporary_expanded_spec = populate_semantictypes(crd[key], expanded_spec[key], basic)
81
+ end
82
+ end
83
+ temporary_expanded_spec ||= {}
84
+ unless temporary_expanded_spec.empty? || parent.nil?
85
+ ::DTK::CrdClient.get_kubeclient({}).merge_patch_semantictype(parent, { expandedSpec: { key => temporary_expanded_spec } }, namespace)
86
+ end
87
+ end
88
+ expanded_spec
89
+ end
90
+
61
91
  def update_current(previous_value, path, field_name, field_value)
62
- tags = { }
92
+ tags = {}
63
93
  previous_value.each_pair do |key, value|
64
- tags[key] = value if key[0..0] != "_" && key != "result" && key != "table"
94
+ tags[key] = value if key[0..0] != '_' && key != 'result' && key != 'table'
65
95
  end
66
96
  fields = Hash.new
67
97
  fields[field_name.to_sym] = field_value
68
98
  validate_fields(get_partial_definition(path), fields)
69
99
  @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"
100
+ name: previous_value['_measurement'],
101
+ tags: tags,
102
+ fields: fields,
103
+ time: (Time.new.to_f * 1000).to_i
104
+ })
76
105
  end
77
106
 
78
107
  def get_influxdb_properties(inventory, parent_type = [:top], parent_name = nil)
79
108
  content_to_write = []
80
109
  properties = { }
81
110
  inventory.each_pair do |key, value|
82
- if value.class.to_s == "Array"
111
+ if value.class.to_s == 'Array'
83
112
  inventory[key].each do |element|
84
113
  get_influxdb_properties(element, parent_type.push(key), inventory[:name])
85
114
  end
@@ -102,12 +131,10 @@ module DTK::State
102
131
  end
103
132
 
104
133
  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
134
+ validate_tags(partial_definition, request[:tags])
135
+ validate_fields(partial_definition, request[:fields])
136
+ rescue => e
137
+ raise e
111
138
  end
112
139
 
113
140
  def get_tags_and_fields(partial_definition, properties)
@@ -115,7 +142,7 @@ module DTK::State
115
142
  fields = { }
116
143
  properties.each_pair do |key, value|
117
144
  if partial_definition[key].nil?
118
- fail "Property '#{key}' not found in the definition of attribute"
145
+ raise "Property '#{key}' not found in the definition of attribute"
119
146
  else
120
147
  if partial_definition[key][:metric].nil? || partial_definition[key][:metric] == false
121
148
  tags[key] = value
@@ -131,14 +158,12 @@ module DTK::State
131
158
  end
132
159
 
133
160
  def validate_fields(partial_definition, fields)
134
-
135
161
  partial_definition.each_pair do |key, value|
136
162
  next if key == :required || value[:metric] == (false || nil)
137
-
138
163
  if fields[key].nil?
139
- fail "Field #{key} is missing. Validation of request failed!"
164
+ raise "Field #{key} is missing. Validation of request failed!"
140
165
  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"
166
+ raise "Defined type for SemanticType attribute property '#{key}' is #{value[:type].capitalize}, #{fields[key].class} provided"
142
167
  end
143
168
  end
144
169
  end
@@ -146,20 +171,19 @@ module DTK::State
146
171
  def validate_tags(partial_definition, tags)
147
172
  partial_definition.each_pair do |key, value|
148
173
  next if key == :required || value[:metric] == true
149
-
150
174
  if tags[key].nil?
151
175
  if value[:default].nil?
152
- fail "Property #{key} is missing. Validation of request failed!"
153
- else
176
+ raise "Property #{key} is missing. Validation of request failed!"
177
+ else
154
178
  tags[key] = value[:default]
155
179
  end
156
- else
180
+ else
157
181
  type = tags[key].class
158
- type = "Boolean" if type == TrueClass || type == FalseClass
182
+ type = 'Boolean' if type == TrueClass || type == FalseClass
159
183
  if value[:type].capitalize == type.to_s
160
184
  next
161
185
  else
162
- fail "Defined type for SemanticType attribute property '#{key}' is #{value[:type].capitalize}, #{type} provided"
186
+ raise "Defined type for SemanticType attribute property '#{key}' is #{value[:type].capitalize}, #{type} provided"
163
187
  end
164
188
  end
165
189
  end
@@ -167,24 +191,25 @@ module DTK::State
167
191
 
168
192
  def get_partial_definition(path)
169
193
  i = 0
170
- definition = { }
171
- semantictype_crd = crd_content[:properties]
194
+ definition = {}
195
+ semantictype_crd = crd_content.to_h[:properties]
196
+ expanded_spec = expanded_semantictype_spec.to_h
172
197
  while i < path.length
173
198
  if path[i].to_sym == :top
174
199
  semantictype_crd.each_pair do |key, value|
175
200
  if key == :required
176
201
  definition[key] = value
177
202
  else
178
- definition[key] = value if value[:type] != "array"
203
+ basic, semantictype = value[:type].split(':')
204
+ semantictype.nil? ? definition[key] = value : definition[key] = semantictype_crd[key] if basic != 'array'
179
205
  end
180
206
  end
181
207
  else
182
208
  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"
209
+ expanded_spec[path[i].to_sym].each_pair do |key, value|
210
+ definition[key] = value unless value[:type].nil?
186
211
  end
187
- semantictype_crd = semantictype_crd[path[i].to_sym][:items][:properties]
212
+ expanded_spec = expanded_spec[path[i].to_sym]
188
213
  end
189
214
  i+=1
190
215
  end
@@ -192,7 +217,7 @@ module DTK::State
192
217
  end
193
218
 
194
219
  def get_path_to_object(parameter)
195
- path = ["top"]
220
+ path = ['top']
196
221
  array = parameter.split('/')
197
222
  array.each do |element|
198
223
  path.push(element.split(':')[1])
@@ -202,19 +227,18 @@ module DTK::State
202
227
 
203
228
  def validate_parameter(parameter)
204
229
  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'"
230
+ parameter.split('/').each_with_index do |param, index|
231
+ name, type = param.split(':')
232
+ raise unless name && type
233
+
234
+ array_of_parameters.push({
235
+ name: name,
236
+ type: type
237
+ })
217
238
  end
239
+ array_of_parameters
240
+ rescue => e
241
+ raise "Could not resolve parameter '#{parameter}'. It should be in format: 'parent:type/child:type'"
218
242
  end
219
243
  end
220
244
  end
@@ -9,7 +9,7 @@ module DTK::State
9
9
  def initialize(namespace, name, content)
10
10
  @name = name
11
11
  @namespace = namespace
12
- @executable_actions = content[:spec][:actions]
12
+ @executable_actions = content[:spec][:actions] || {}
13
13
  @attribute_type_info = AttributeTypeInfo.create_from_kube_hash(content[:spec][:attributes] || {})
14
14
  end
15
15
 
@@ -19,6 +19,19 @@ module DTK::State
19
19
  end
20
20
  end
21
21
 
22
+ def to_hash
23
+ type_info = {}
24
+
25
+ type_info.merge!(name: @name) if @name
26
+ type_info.merge!(type: @type) if @type
27
+ type_info.merge!(required: @required) if @required
28
+ type_info.merge!(dynamic: @dynamic) if @dynamic
29
+ type_info.merge!(temporal: @temporal) if @temporal
30
+ type_info.merge!(encrypted: @encrypted) if @encrypted
31
+
32
+ type_info
33
+ end
34
+
22
35
  end
23
36
  end
24
37
  end
@@ -2,14 +2,19 @@ module DTK::State
2
2
  class CrdAssembly
3
3
  ASSEMBLY_CRD_VERSION = ENV["ASSEMBLY_CRD_VERSION"]
4
4
 
5
- attr_reader :name, :namespace, :crd_content, :components, :references
5
+ attr_reader :name, :namespace, :crd_content, :references, :component_objs
6
+ attr_accessor :components
6
7
 
7
8
  def initialize(namespace, name, crd_content)
8
- @name = name
9
- @namespace = namespace
10
- @crd_content = crd_content
11
- @references = crd_content.references
12
- @components = crd_content[:spec][:components]
9
+ @name = name
10
+ @namespace = namespace
11
+ @api_version = crd_content.apiVersion
12
+ @kind = crd_content.kind
13
+ @metadata = crd_content.metadata
14
+ # @crd_content = crd_content
15
+ @references = crd_content.references
16
+ @components = crd_content[:spec][:components] || []
17
+ # @component_objs = Component.create_from_kube_array(@components, self)
13
18
  end
14
19
 
15
20
  def self.get(namespace, name, opts = {})
@@ -52,6 +57,51 @@ module DTK::State
52
57
  output
53
58
  end
54
59
 
60
+ # TODO: this is a temporal solution to avoid breaking backward compatibility; will change this soon
61
+ def self.get_with_influx_data(namespace, assembly_name, opts = {})
62
+ assembly = get(namespace, assembly_name, opts)
63
+
64
+ components_hash = {}
65
+ assembly.components.each do |assembly_component|
66
+ cmp_name = assembly_component.to_hash.keys.first
67
+ components_hash[cmp_name] = assembly_component[cmp_name].to_hash
68
+ end
69
+
70
+ component_objs = Component.create_from_kube_array(assembly.components, assembly)
71
+
72
+ component_objs.each do |component_obj|
73
+ component_name = component_obj.name
74
+ attr_type_info = component_obj.component_def.attribute_type_info
75
+ attr_type_info.each do |attr_info|
76
+ if attr_info.temporal
77
+ attribute_name = attr_info.name
78
+ influxdb = ::DTK::State::Component::Attribute::Influxdb.new(:attributes)
79
+ influxdb_attribute = influxdb.get(namespace, component_name, assembly_name, attribute_name, opts)
80
+ if valid_attribute = influxdb_attribute.first
81
+ value = valid_attribute['_value']
82
+ if components_hash[component_name][:attributes][attribute_name].is_a?(String)
83
+ components_hash[component_name][:attributes][attribute_name] = value
84
+ else
85
+ components_hash[component_name][:attributes][attribute_name][:value] = value
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ assembly.components = components_hash
92
+ assembly
93
+ end
94
+
95
+ def to_hash
96
+ {
97
+ apiVersion: @api_version,
98
+ kind: @kind,
99
+ metadata: @metadata.to_hash,
100
+ references: @references.to_hash,
101
+ spec: { components: @components.to_hash }
102
+ }
103
+ end
104
+
55
105
  private
56
106
 
57
107
  def self.check_for_missing_components(crd_components, requested_components)
@@ -0,0 +1,26 @@
1
+ module DTK::State
2
+ class Workflow
3
+ require_relative 'workflow_instance/attribute_type_info'
4
+
5
+ WORKFLOW_CRD_VERSION = ENV["WORKFLOW_CRD_VERSION"]
6
+
7
+ attr_reader :name, :namespace, :references, :assembly, :workflow, :attribute_type_info
8
+
9
+ def initialize(namespace, name, crd_content)
10
+ @name = name
11
+ @namespace = namespace
12
+
13
+ @references = crd_content.references
14
+ @assembly = @references.assembly
15
+ @workflow = crd_content.spec.workflow || {}
16
+
17
+ @attribute_type_info = ::DTK::State::WorkflowInstance::AttributeTypeInfo.create_from_kube_hash(crd_content.spec.attributes.to_h || {})
18
+ end
19
+
20
+ def self.get(namespace, name, opts = {})
21
+ opts[:apiVersion] = WORKFLOW_CRD_VERSION
22
+ workflow = ::DTK::CrdClient.get_kubeclient(opts).get_workflow(name, namespace)
23
+ Workflow.new(namespace, name, workflow)
24
+ end
25
+ end
26
+ end
@@ -4,16 +4,24 @@ module DTK::State
4
4
 
5
5
  WORKFLOW_INSTANCE_CRD_VERSION = ENV["WORKFLOW_INSTANCE_CRD_VERSION"]
6
6
 
7
- attr_reader :name, :namespace, :assembly, :workflow_template, :attributes, :workflow, :attribute_type_info
7
+ attr_reader :name, :namespace, :assembly, :workflow_template, :attributes, :attribute_type_info, :status, :workflow
8
+ attr_accessor :workflow
8
9
 
9
10
  def initialize(namespace, name, crd_content)
10
11
  @name = name
11
12
  @namespace = namespace
12
- @assembly = crd_content.references.assembly
13
- @workflow_template = crd_content.references.workflow
14
- @attributes = crd_content.spec.attributes
15
- @workflow = crd_content.spec.workflow
16
- @attribute_type_info = AttributeTypeInfo.create_from_kube_hash(@attributes.to_h || {})
13
+
14
+ @api_version = crd_content.apiVersion
15
+ @kind = crd_content.kind
16
+ @metadata = crd_content.metadata
17
+
18
+ @references = crd_content.references
19
+ @assembly = @references.assembly
20
+ @workflow_template = @references.workflow
21
+
22
+ @attributes = crd_content.spec.attributes || {}
23
+ @status = crd_content.spec.status || {}
24
+ @workflow = crd_content.spec.workflow || {}
17
25
  end
18
26
 
19
27
  def self.get(namespace, name, opts = {})
@@ -22,6 +30,47 @@ module DTK::State
22
30
  WorkflowInstance.new(namespace, name, workflow_instance)
23
31
  end
24
32
 
33
+ def self.get_with_influx_data(namespace, workflow_instance_name, opts = {})
34
+ workflow_instance = get(namespace, workflow_instance_name, opts)
35
+ return unless workflow_instance
36
+
37
+ workflow_instance.workflow[:subtasks].each do |subtask|
38
+ component_name, action_name = subtask[:component].split('.')
39
+ assembly_name = workflow_instance.assembly[:name]
40
+
41
+ executable_action = ::DTK::State::ExecutableAction.get(namespace, assembly_name, component_name, action_name, opts)
42
+ attr_type_info = executable_action.attribute_type_info
43
+
44
+ attr_type_info.each do |attr_info|
45
+ if attr_info.temporal
46
+ attribute_name = attr_info.name
47
+ influxdb = ::DTK::State::Component::Attribute::Influxdb.new(:attributes)
48
+ influxdb_attribute = influxdb.get(namespace, component_name, assembly_name, attribute_name, opts)
49
+ if valid_attribute = influxdb_attribute.first
50
+ value = valid_attribute['_value']
51
+ subtask[:attributes][attribute_name] = value
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ workflow_instance
58
+ end
59
+
60
+ def to_hash
61
+ {
62
+ apiVersion: @api_version,
63
+ kind: @kind,
64
+ metadata: @metadata.to_hash,
65
+ references: @references.to_hash,
66
+ spec: {
67
+ attributes: @attributes.to_hash,
68
+ status: @status.to_hash,
69
+ workflow: @workflow.to_hash
70
+ }
71
+ }
72
+ end
73
+
25
74
  def self.get_attributes(namespace, name, opts = {})
26
75
  workflow_instance = get(namespace, name, opts)
27
76
  workflow_instance.attributes.to_h
@@ -95,5 +144,38 @@ module DTK::State
95
144
  action
96
145
  end
97
146
 
147
+ def get_workflow_template(opts = {})
148
+ Workflow.get(@workflow_template.namespace, @workflow_template.name, opts)
149
+ end
150
+
151
+ def attribute_metadata
152
+ attributes = @attributes.to_hash
153
+ attr_type_info = get_workflow_template.attribute_type_info
154
+ attribute_metadata = {}
155
+
156
+ attr_type_info.each do |attr_info|
157
+ attr_info_hash = attr_info.to_hash
158
+ attribute_name = attr_info_hash[:name].to_sym
159
+
160
+ if attribute = attributes[attribute_name]
161
+ if attribute.is_a?(String)
162
+ attribute = { value: attribute }
163
+ end
164
+
165
+ attribute_metadata[attribute_name] = attr_info_hash.merge(attribute)
166
+ end
167
+ end
168
+
169
+ attribute_metadata
170
+ end
171
+
172
+ def attribute_values
173
+ attribute_with_values = {}
174
+ @attributes.each_pair do |name, content|
175
+ attribute_with_values.merge!(name => content[:value])
176
+ end
177
+ attribute_with_values
178
+ end
179
+
98
180
  end
99
181
  end
@@ -21,6 +21,19 @@ module DTK::State
21
21
  end
22
22
  end
23
23
 
24
+ def to_hash
25
+ type_info = {}
26
+
27
+ type_info.merge!(name: @name) if @name
28
+ type_info.merge!(type: @type) if @type
29
+ type_info.merge!(required: @required) if @required
30
+ type_info.merge!(dynamic: @dynamic) if @dynamic
31
+ type_info.merge!(temporal: @temporal) if @temporal
32
+ type_info.merge!(encrypted: @encrypted) if @encrypted
33
+
34
+ type_info
35
+ end
36
+
24
37
  end
25
38
  end
26
39
  end
@@ -1,3 +1,5 @@
1
- module Utils
2
- require_relative 'utils/log'
1
+ module DTK
2
+ module Utils
3
+ require_relative 'utils/log'
4
+ end
3
5
  end
@@ -1,4 +1,4 @@
1
- module Utils
1
+ module DTK::Utils
2
2
  module Log
3
3
  require 'logger'
4
4
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = 'persistence-providers'
3
- spec.version = '0.0.4.1'
3
+ spec.version = '0.0.5'
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.4.1
4
+ version: 0.0.5
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-27 00:00:00.000000000 Z
11
+ date: 2020-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kubeclient
@@ -77,6 +77,7 @@ files:
77
77
  - lib/state/crd_assembly.rb
78
78
  - lib/state/executable_action.rb
79
79
  - lib/state/executable_action/attribute_type_info.rb
80
+ - lib/state/workflow.rb
80
81
  - lib/state/workflow_instance.rb
81
82
  - lib/state/workflow_instance/attribute_type_info.rb
82
83
  - lib/utils.rb