floe 0.15.1 → 0.16.0

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: 6f21cf2fcc6a7fa9f7536e0cca328d101a867c389f53f768e4746b6e69f643a5
4
- data.tar.gz: f3d82401842f66504afdeaa4b051db01d5fcb9e79b704af368712d68b4950251
3
+ metadata.gz: 2d592d8fe18169e547f72b096e1135e93775f15027614f7c9dcdd97714896b44
4
+ data.tar.gz: dcad7afbd661be7f53566c143d48f9abd945ec15ceff24ed38d4c6ae14c34b3d
5
5
  SHA512:
6
- metadata.gz: 3e73dbdd868ec57b8138a9e4b0b529c0f2c44cdb21d43c0ae29ca9094512f4044cc621a38e4ac217bf6b17e13f1ef3a361cf5917023eab87d30c7b4cc90eccfc
7
- data.tar.gz: e174fabde62d6348f8517f7c2d019600b34612f5b8d822eb83c2c5579f5e224596b6edaec383bfe9cce75c3260e50a4a0b744764119cd96e2a973f92b49b7d5a
6
+ metadata.gz: 1246c428448b2631a994095a0919cd533c1c5b52d814c13fab6ab1a9a54599388e6611eef3e472dd5cf330b43987e3b38e2833bba5dc5914cd14ea7e9bf22a47
7
+ data.tar.gz: 576450ba34cdb2d263792c88b72f8710cc420ade67d28228f075917cb1ae6b9d27b90a6e9a278243960d3e562f58228d159214f06ec2fdfb9b895ee642ef9c7a
data/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.16.0] - 2025-04-08
8
+ ### Added
9
+ - Add Map state ItemBatcher/ItemSelector support ([#294](https://github.com/ManageIQ/floe/pull/294))
10
+
11
+ ### Fixed
12
+ - Fix JSON.parse exception expectation ([#300](https://github.com/ManageIQ/floe/pull/300))
13
+
7
14
  ## [0.15.1] - 2024-11-21
8
15
  ### Fixed
9
16
  - Fix Map/Parallel States checking container_runner#status! of finished states ([#296](https://github.com/ManageIQ/floe/pull/296))
@@ -272,7 +279,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
272
279
  ### Added
273
280
  - Initial release
274
281
 
275
- [Unreleased]: https://github.com/ManageIQ/floe/compare/v0.15.1...HEAD
282
+ [Unreleased]: https://github.com/ManageIQ/floe/compare/v0.16.0...HEAD
283
+ [0.16.0]: https://github.com/ManageIQ/floe/compare/v0.15.1...v0.16.0
276
284
  [0.15.1]: https://github.com/ManageIQ/floe/compare/v0.15.0...v0.15.1
277
285
  [0.15.0]: https://github.com/ManageIQ/floe/compare/v0.14.0...v0.15.0
278
286
  [0.14.0]: https://github.com/ManageIQ/floe/compare/v0.13.1...v0.14.0
data/floe.gemspec CHANGED
@@ -37,6 +37,7 @@ Gem::Specification.new do |spec|
37
37
  spec.add_dependency "kubeclient", "~>4.7"
38
38
  spec.add_dependency "optimist", "~>3.0"
39
39
  spec.add_dependency "parslet", "~>2.0"
40
+ spec.add_dependency "json", "~>2.10"
40
41
 
41
42
  spec.add_development_dependency "manageiq-style", ">= 1.5.2"
42
43
  spec.add_development_dependency "rake", "~> 13.0"
data/lib/floe/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Floe
4
- VERSION = "0.15.1"
4
+ VERSION = "0.16.0"
5
5
  end
@@ -80,27 +80,27 @@ module Floe
80
80
  # rubocop:enable Naming/PredicateName
81
81
  # rubocop:enable Style/OptionalBooleanParameter
82
82
 
83
- def equals?(lhs, rhs)
83
+ def op_equals?(lhs, rhs)
84
84
  lhs == rhs
85
85
  end
86
86
 
87
- def lessthan?(lhs, rhs)
87
+ def op_lessthan?(lhs, rhs)
88
88
  lhs < rhs
89
89
  end
90
90
 
91
- def greaterthan?(lhs, rhs)
91
+ def op_greaterthan?(lhs, rhs)
92
92
  lhs > rhs
93
93
  end
94
94
 
95
- def lessthanequals?(lhs, rhs)
95
+ def op_lessthanequals?(lhs, rhs)
96
96
  lhs <= rhs
97
97
  end
98
98
 
99
- def greaterthanequals?(lhs, rhs)
99
+ def op_greaterthanequals?(lhs, rhs)
100
100
  lhs >= rhs
101
101
  end
102
102
 
103
- def matches?(lhs, rhs)
103
+ def op_matches?(lhs, rhs)
104
104
  lhs.match?(Regexp.escape(rhs).gsub('\*', '.*?'))
105
105
  end
106
106
 
@@ -111,7 +111,7 @@ module Floe
111
111
  if (match_values = OPERATION.match(key))
112
112
  @compare_key = key
113
113
  @type, operator, @path = match_values.captures
114
- @operation = "#{operator.downcase}?".to_sym
114
+ @operation = "op_#{operator.downcase}?".to_sym
115
115
  @compare_predicate = parse_predicate(type)
116
116
  break
117
117
  end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Floe
4
+ class Workflow
5
+ class ItemBatcher
6
+ include ValidationMixin
7
+
8
+ attr_reader :name, :batch_input, :max_items_per_batch, :max_items_per_batch_path, :max_input_bytes_per_batch, :max_input_bytes_per_batch_path
9
+
10
+ def initialize(payload, name)
11
+ @name = name
12
+
13
+ @batch_input = PayloadTemplate.new(payload["BatchInput"]) if payload["BatchInput"]
14
+ @max_items_per_batch = payload["MaxItemsPerBatch"]
15
+ @max_input_bytes_per_batch = payload["MaxInputBytesPerBatch"]
16
+
17
+ @max_items_per_batch_path = ReferencePath.new(payload["MaxItemsPerBatchPath"]) if payload["MaxItemsPerBatchPath"]
18
+ @max_input_bytes_per_batch_path = ReferencePath.new(payload["MaxInputBytesPerBatchPath"]) if payload["MaxInputBytesPerBatchPath"]
19
+
20
+ validate!
21
+ end
22
+
23
+ def value(context, input, state_input = nil)
24
+ state_input ||= input
25
+
26
+ output = batch_input ? batch_input.value(context, state_input) : {}
27
+
28
+ input.each_slice(max_items(context, state_input)).map do |batch|
29
+ output.merge("Items" => batch)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def max_items(context, state_input)
36
+ return max_items_per_batch if max_items_per_batch
37
+ return if max_items_per_batch_path.nil?
38
+
39
+ result = max_items_per_batch_path.value(context, state_input)
40
+ raise runtime_field_error!("MaxItemsPerBatchPath", result, "must be a positive integer") if result.nil? || !result.kind_of?(Integer) || result <= 0
41
+
42
+ result
43
+ end
44
+
45
+ def validate!
46
+ if [max_items_per_batch, max_items_per_batch_path].all?(&:nil?)
47
+ parser_error!("must have one of \"MaxItemsPerBatch\", \"MaxItemsPerBatchPath\"")
48
+ end
49
+
50
+ parser_error!("must not specify both \"MaxItemsPerBatch\" and \"MaxItemsPerBatchPath\"") if max_items_per_batch && max_items_per_batch_path
51
+ parser_error!("must not specify both \"MaxInputBytesPerBatch\" and \"MaxInputBytesPerBatchPath\"") if max_input_bytes_per_batch && max_input_bytes_per_batch_path
52
+
53
+ if max_items_per_batch && (!max_items_per_batch.kind_of?(Integer) || max_items_per_batch <= 0)
54
+ invalid_field_error!("MaxItemsPerBatch", max_items_per_batch, "must be a positive integer")
55
+ end
56
+ if max_input_bytes_per_batch && (!max_input_bytes_per_batch.kind_of?(Integer) || max_input_bytes_per_batch <= 0)
57
+ invalid_field_error!("MaxInputBytesPerBatch", max_input_bytes_per_batch, "must be a positive integer")
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -31,8 +31,8 @@ module Floe
31
31
  @item_processor = ItemProcessor.new(payload["ItemProcessor"], name)
32
32
  @items_path = ReferencePath.new(payload.fetch("ItemsPath", "$"))
33
33
  @item_reader = payload["ItemReader"]
34
- @item_selector = payload["ItemSelector"]
35
- @item_batcher = payload["ItemBatcher"]
34
+ @item_selector = PayloadTemplate.new(payload["ItemSelector"]) if payload["ItemSelector"]
35
+ @item_batcher = ItemBatcher.new(payload["ItemBatcher"], name + ["ItemBatcher"]) if payload["ItemBatcher"]
36
36
  @result_writer = payload["ResultWriter"]
37
37
  @max_concurrency = payload["MaxConcurrency"]&.to_i
38
38
  @tolerated_failure_percentage = payload["ToleratedFailurePercentage"]&.to_i
@@ -43,7 +43,9 @@ module Floe
43
43
 
44
44
  def process_input(context)
45
45
  input = super
46
- items_path.value(context, input)
46
+ input = items_path.value(context, input)
47
+ input = item_batcher.value(context, input, context.state["Input"]) if item_batcher
48
+ input
47
49
  end
48
50
 
49
51
  def start(context)
@@ -51,7 +53,20 @@ module Floe
51
53
 
52
54
  input = process_input(context)
53
55
 
54
- context.state["ItemProcessorContext"] = input.map { |item| Context.new({"Execution" => {"Id" => context.execution["Id"]}}, :input => item.to_json).to_h }
56
+ context.state["ItemProcessorContext"] = input.map.with_index do |item, index|
57
+ item_processor_context = {
58
+ "Execution" => {
59
+ "Id" => context.execution["Id"]
60
+ },
61
+ "Map" => {
62
+ "Item" => {"Index" => index, "Value" => item}
63
+ }
64
+ }
65
+
66
+ item_processor_input = item_selector ? item_selector.value(item_processor_context, context.state["Input"]) : item
67
+
68
+ Context.new(item_processor_context, :input => item_processor_input.to_json).to_h
69
+ end
55
70
  end
56
71
 
57
72
  def end?
data/lib/floe.rb CHANGED
@@ -20,6 +20,7 @@ require_relative "floe/workflow/choice_rule/or"
20
20
  require_relative "floe/workflow/choice_rule/and"
21
21
  require_relative "floe/workflow/choice_rule/data"
22
22
  require_relative "floe/workflow/context"
23
+ require_relative "floe/workflow/item_batcher"
23
24
  require_relative "floe/workflow/item_processor"
24
25
  require_relative "floe/workflow/intrinsic_function"
25
26
  require_relative "floe/workflow/intrinsic_function/parser"
data/renovate.json CHANGED
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
- "extends": [
4
- "config:base"
5
- ]
3
+ "inheritConfig": true,
4
+ "inheritConfigRepoName": "manageiq/renovate-config"
6
5
  }
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: floe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.1
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ManageIQ Developers
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-11-21 00:00:00.000000000 Z
10
+ date: 2025-04-08 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: awesome_spawn
@@ -94,6 +93,20 @@ dependencies:
94
93
  - - "~>"
95
94
  - !ruby/object:Gem::Version
96
95
  version: '2.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: json
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '2.10'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '2.10'
97
110
  - !ruby/object:Gem::Dependency
98
111
  name: manageiq-style
99
112
  requirement: !ruby/object:Gem::Requirement
@@ -165,7 +178,6 @@ dependencies:
165
178
  - !ruby/object:Gem::Version
166
179
  version: '0'
167
180
  description: Floe is a runner for Amazon States Language workflows.
168
- email:
169
181
  executables:
170
182
  - floe
171
183
  extensions: []
@@ -213,6 +225,7 @@ files:
213
225
  - lib/floe/workflow/intrinsic_function.rb
214
226
  - lib/floe/workflow/intrinsic_function/parser.rb
215
227
  - lib/floe/workflow/intrinsic_function/transformer.rb
228
+ - lib/floe/workflow/item_batcher.rb
216
229
  - lib/floe/workflow/item_processor.rb
217
230
  - lib/floe/workflow/path.rb
218
231
  - lib/floe/workflow/payload_template.rb
@@ -243,7 +256,6 @@ metadata:
243
256
  homepage_uri: https://github.com/ManageIQ/floe
244
257
  source_code_uri: https://github.com/ManageIQ/floe
245
258
  changelog_uri: https://github.com/ManageIQ/floe/blob/master/CHANGELOG.md
246
- post_install_message:
247
259
  rdoc_options: []
248
260
  require_paths:
249
261
  - lib
@@ -258,8 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
270
  - !ruby/object:Gem::Version
259
271
  version: '0'
260
272
  requirements: []
261
- rubygems_version: 3.4.20
262
- signing_key:
273
+ rubygems_version: 3.6.6
263
274
  specification_version: 4
264
275
  summary: Floe is a runner for Amazon States Language workflows.
265
276
  test_files: []