floe 0.6.1 → 0.7.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: b92b3c488e49ea77447b370e9152c49e11036e8295c6a781feda666662927f9e
4
- data.tar.gz: c553deab6491c9876e28a816cb2422a1318ac6f91a9f9f75cbfc5a144a84d248
3
+ metadata.gz: 8e3870ee415e08857191014d61d92dac1b84be70aeff69bed7dbb6dd6f5f7af3
4
+ data.tar.gz: f6695006e7043837a078a8092ba1c544e23750a9179018ed29e84520e78424eb
5
5
  SHA512:
6
- metadata.gz: 3f5c210d2a745aaed8e3419e228465203dcebb02ee678c1d2b47285083e1f154118c25864e51360d3d062ca0cfade9baa84f5a932804b586f26607a195acc710
7
- data.tar.gz: 238fd469915e8682c449abd26e1950f68fd4b032a32fcace11130109d46dc6962b29e4ce381734d167f5328ef16ee2fdd4bb250f844644abebc571fc001ab2dd
6
+ metadata.gz: ada0c662fa9f4c300ca977029b3c522a5ba36adf37485260dfccba5961064adfc513853beb1b992ca9199856b457bb6f66c8f4d60918157cb4579cf0655d7a7b
7
+ data.tar.gz: f6918df717d7e5c29d7298c1f9076d77515a3033247fefde072cdfd59797227defcec0087189d58945bbbbd528da3b5d876af612479bd1d2754fc7dc78db8c81
data/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.7.0] - 2023-12-18
8
+ ### Changed
9
+ - Remove the dependency on more_core_extensions in ReferencePath ([#144](https://github.com/ManageIQ/floe/pull/144))
10
+
11
+ ### Added
12
+ - Implement `ReferencePath#get` ([#144](https://github.com/ManageIQ/floe/pull/144))
13
+ - Allow a State to set a value in Credentials for subsequent states ([#145](https://github.com/ManageIQ/floe/pull/145))
14
+
7
15
  ## [0.6.1] - 2023-11-21
8
16
  ### Fixed
9
17
  - Return an error payload if run_async! fails ([#143](https://github.com/ManageIQ/floe/pull/143))
@@ -106,7 +114,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
106
114
  ### Added
107
115
  - Initial release
108
116
 
109
- [Unreleased]: https://github.com/ManageIQ/floe/compare/v0.6.1...HEAD
117
+ [Unreleased]: https://github.com/ManageIQ/floe/compare/v0.7.0...HEAD
118
+ [0.7.0]: https://github.com/ManageIQ/floe/compare/v0.6.1...v0.7.0
110
119
  [0.6.1]: https://github.com/ManageIQ/floe/compare/v0.6.0...v0.6.1
111
120
  [0.6.0]: https://github.com/ManageIQ/floe/compare/v0.5.0...v0.6.0
112
121
  [0.5.0]: https://github.com/ManageIQ/floe/compare/v0.4.1...v0.5.0
data/README.md CHANGED
@@ -51,6 +51,38 @@ You can provide that at runtime via the `--credentials` parameter:
51
51
  bundle exec ruby exe/floe --workflow my-workflow.asl --credentials='{"roleArn": "arn:aws:iam::111122223333:role/LambdaRole"}'
52
52
  ```
53
53
 
54
+ If you need to set a credential at runtime you can do that by using the `"ResultPath": "$.Credentials"` directive, for example to user a username/password to login and get a Bearer token:
55
+
56
+ ```
57
+ bundle exec ruby exe/floe --workflow my-workflow.asl --credentials='{"username": "user", "password": "pass"}'
58
+ ```
59
+
60
+ ```json
61
+ {
62
+ "StartAt": "Login",
63
+ "States": {
64
+ "Login": {
65
+ "Type": "Task",
66
+ "Resource": "docker://login:latest",
67
+ "Credentials": {
68
+ "username.$": "$.username",
69
+ "password.$": "$.password"
70
+ },
71
+ "ResultPath": "$.Credentials",
72
+ "Next": "DoSomething"
73
+ },
74
+ "DoSomething": {
75
+ "Type": "Task",
76
+ "Resource": "docker://do-something:latest",
77
+ "Credentials": {
78
+ "token.$": "$.bearer_token"
79
+ },
80
+ "End": true
81
+ }
82
+ }
83
+ }
84
+ ```
85
+
54
86
  ### Ruby Library
55
87
 
56
88
  ```ruby
@@ -0,0 +1,26 @@
1
+ {
2
+ "Comment": "An example showing how to set a credential.",
3
+ "StartAt": "Login",
4
+ "States": {
5
+ "Login": {
6
+ "Type": "Task",
7
+ "Resource": "docker://docker.io/agrare/echo:latest",
8
+ "Parameters": {
9
+ "ECHO": "TOKEN"
10
+ },
11
+ "ResultPath": "$.Credentials",
12
+ "ResultSelector": {
13
+ "bearer_token.$": "$.echo"
14
+ },
15
+ "Next": "DoSomething"
16
+ },
17
+ "DoSomething": {
18
+ "Type": "Task",
19
+ "Resource": "docker://docker.io/agrare/hello-world:latest",
20
+ "Credentials": {
21
+ "bearer_token.$": "$.bearer_token"
22
+ },
23
+ "End": true
24
+ }
25
+ }
26
+ }
data/floe.gemspec CHANGED
@@ -32,6 +32,5 @@ Gem::Specification.new do |spec|
32
32
  spec.add_dependency "awesome_spawn", "~>1.0"
33
33
  spec.add_dependency "jsonpath", "~>1.1"
34
34
  spec.add_dependency "kubeclient", "~>4.7"
35
- spec.add_dependency "more_core_extensions"
36
35
  spec.add_dependency "optimist", "~>3.0"
37
36
  end
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.6.1".freeze
4
+ VERSION = "0.7.0".freeze
5
5
  end
@@ -9,6 +9,8 @@ module Floe
9
9
  end
10
10
  end
11
11
 
12
+ attr_reader :payload
13
+
12
14
  def initialize(payload)
13
15
  @payload = payload
14
16
 
@@ -28,10 +30,6 @@ module Floe
28
30
 
29
31
  results.count < 2 ? results.first : results
30
32
  end
31
-
32
- private
33
-
34
- attr_reader :payload
35
33
  end
36
34
  end
37
35
  end
@@ -4,37 +4,54 @@ module Floe
4
4
  class Workflow
5
5
  class ReferencePath < Path
6
6
  class << self
7
+ def get(payload, context)
8
+ new(payload).get(context)
9
+ end
10
+
7
11
  def set(payload, context, value)
8
12
  new(payload).set(context, value)
9
13
  end
10
14
  end
11
15
 
12
- def initialize(*)
13
- require "more_core_extensions/core_ext/hash/nested"
14
- require "more_core_extensions/core_ext/array/nested"
16
+ attr_reader :path
15
17
 
18
+ def initialize(*)
16
19
  super
17
20
 
18
21
  raise Floe::InvalidWorkflowError, "Invalid Reference Path" if payload.match?(/@|,|:|\?/)
22
+ @path = JsonPath.new(payload)
23
+ .path[1..]
24
+ .map { |v| v.match(/\[(?<name>.+)\]/)["name"] }
25
+ .map { |v| v[0] == "'" ? v.delete("'") : v.to_i }
26
+ .compact
27
+ end
28
+
29
+ def get(context)
30
+ return context if path.empty?
31
+
32
+ context.dig(*path)
19
33
  end
20
34
 
21
35
  def set(context, value)
22
36
  result = context.dup
23
37
 
24
- path = JsonPath.new(payload)
25
- .path[1..]
26
- .map { |v| v.match(/\[(?<name>.+)\]/)["name"] }
27
- .map { |v| v[0] == "'" ? v.delete("'") : v.to_i }
28
- .compact
29
-
30
38
  # If the payload is '$' then merge the value into the context
31
- # otherwise use store path to set the value to a sub-key
39
+ # otherwise store the value under the path
32
40
  #
33
41
  # TODO: how to handle non-hash values, raise error if path=$ and value not a hash?
34
42
  if path.empty?
35
43
  result.merge!(value)
36
44
  else
37
- result.store_path(path, value)
45
+ child = result
46
+ keys = path.dup
47
+ last_key = keys.pop
48
+
49
+ keys.each do |key|
50
+ child[key] = {} if child[key].nil?
51
+ child = child[key]
52
+ end
53
+
54
+ child[last_key] = value
38
55
  end
39
56
 
40
57
  result
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Floe
4
+ class Workflow
5
+ module States
6
+ module InputOutputMixin
7
+ def process_input(input)
8
+ input = input_path.value(context, input)
9
+ input = parameters.value(context, input) if parameters
10
+ input
11
+ end
12
+
13
+ def process_output(input, results)
14
+ return input if results.nil?
15
+ return if output_path.nil?
16
+
17
+ results = result_selector.value(context, results) if @result_selector
18
+ if result_path.payload.start_with?("$.Credentials")
19
+ credentials = result_path.set(workflow.credentials, results)["Credentials"]
20
+ workflow.credentials.merge!(credentials)
21
+ output = input
22
+ else
23
+ output = result_path.set(input, results)
24
+ end
25
+
26
+ output_path.value(context, output)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,6 +4,7 @@ module Floe
4
4
  class Workflow
5
5
  module States
6
6
  class Pass < Floe::Workflow::State
7
+ include InputOutputMixin
7
8
  include NonTerminalMixin
8
9
 
9
10
  attr_reader :end, :next, :result, :parameters, :input_path, :output_path, :result_path
@@ -25,12 +26,11 @@ module Floe
25
26
 
26
27
  def start(input)
27
28
  super
28
- output = input_path.value(context, input)
29
- output = result_path.set(output, result) if result && result_path
30
- output = output_path.value(context, output)
31
29
 
30
+ input = process_input(input)
31
+
32
+ context.output = process_output(input, result)
32
33
  context.next_state = end? ? nil : @next
33
- context.output = output
34
34
  end
35
35
 
36
36
  def running?
@@ -4,6 +4,7 @@ module Floe
4
4
  class Workflow
5
5
  module States
6
6
  class Task < Floe::Workflow::State
7
+ include InputOutputMixin
7
8
  include NonTerminalMixin
8
9
 
9
10
  attr_reader :credentials, :end, :heartbeat_seconds, :next, :parameters,
@@ -49,7 +50,7 @@ module Floe
49
50
 
50
51
  if success?
51
52
  output = parse_output(output)
52
- context.state["Output"] = process_output!(output)
53
+ context.state["Output"] = process_output(context.input.dup, output)
53
54
  context.next_state = next_state
54
55
  else
55
56
  error = parse_error(output)
@@ -126,12 +127,6 @@ module Floe
126
127
  context.state["Error"] = context.output["Error"]
127
128
  end
128
129
 
129
- def process_input(input)
130
- input = input_path.value(context, input)
131
- input = parameters.value(context, input) if parameters
132
- input
133
- end
134
-
135
130
  def parse_error(output)
136
131
  return if output.nil?
137
132
  return output if output.kind_of?(Hash)
@@ -150,16 +145,6 @@ module Floe
150
145
  nil
151
146
  end
152
147
 
153
- def process_output!(results)
154
- output = context.input.dup
155
- return output if results.nil?
156
- return if output_path.nil?
157
-
158
- results = result_selector.value(context, results) if result_selector
159
- output = result_path.set(output, results)
160
- output_path.value(context, output)
161
- end
162
-
163
148
  def next_state
164
149
  end? ? nil : @next
165
150
  end
data/lib/floe.rb CHANGED
@@ -25,6 +25,7 @@ require_relative "floe/workflow/runner/podman"
25
25
  require_relative "floe/workflow/state"
26
26
  require_relative "floe/workflow/states/choice"
27
27
  require_relative "floe/workflow/states/fail"
28
+ require_relative "floe/workflow/states/input_output_mixin"
28
29
  require_relative "floe/workflow/states/map"
29
30
  require_relative "floe/workflow/states/non_terminal_mixin"
30
31
  require_relative "floe/workflow/states/parallel"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: floe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ManageIQ Developers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-21 00:00:00.000000000 Z
11
+ date: 2023-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_spawn
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '4.7'
55
- - !ruby/object:Gem::Dependency
56
- name: more_core_extensions
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: optimist
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -96,6 +82,7 @@ files:
96
82
  - Gemfile
97
83
  - README.md
98
84
  - Rakefile
85
+ - examples/set-credential.asl
99
86
  - examples/workflow.asl
100
87
  - exe/floe
101
88
  - floe.gemspec
@@ -123,6 +110,7 @@ files:
123
110
  - lib/floe/workflow/state.rb
124
111
  - lib/floe/workflow/states/choice.rb
125
112
  - lib/floe/workflow/states/fail.rb
113
+ - lib/floe/workflow/states/input_output_mixin.rb
126
114
  - lib/floe/workflow/states/map.rb
127
115
  - lib/floe/workflow/states/non_terminal_mixin.rb
128
116
  - lib/floe/workflow/states/parallel.rb