persistence-providers 0.0.4.1 → 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: 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