floe 0.6.1 → 0.8.0

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: b92b3c488e49ea77447b370e9152c49e11036e8295c6a781feda666662927f9e
4
- data.tar.gz: c553deab6491c9876e28a816cb2422a1318ac6f91a9f9f75cbfc5a144a84d248
3
+ metadata.gz: c121968c8c3f9c70edaa20c0ab3e7937206623b7c06c0cf0f300aceddcde7814
4
+ data.tar.gz: 943d9e77a9e8309a771e57fee5d6f70e5026a4d254b0da5072b768a99f427d1a
5
5
  SHA512:
6
- metadata.gz: 3f5c210d2a745aaed8e3419e228465203dcebb02ee678c1d2b47285083e1f154118c25864e51360d3d062ca0cfade9baa84f5a932804b586f26607a195acc710
7
- data.tar.gz: 238fd469915e8682c449abd26e1950f68fd4b032a32fcace11130109d46dc6962b29e4ce381734d167f5328ef16ee2fdd4bb250f844644abebc571fc001ab2dd
6
+ metadata.gz: 4fa820c364e8dc3266c2fc1eb29d682e72a9d2ab4d8f154aac3a88ff6d4c35e45e124fe714b80110b52e78a0ab654e25f956bc8a39f45f05f3990c0ab26d01ed
7
+ data.tar.gz: b62ac48c4105497c1d3dd2f2ef9d8aec60c25bcadf71046e8488175705365d0d84facde34c11f0047660b5ab2f4390f13babbe8ba2ab6becf31027f027e0b833
data/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.8.0] - 2024-01-17
8
+ ### Added
9
+ - Add CLI shorthand options for docker runner ([#147](https://github.com/ManageIQ/floe/pull/147))
10
+ - Run multiple workflows in exe/floe ([#149](https://github.com/ManageIQ/floe/pull/149))
11
+ - Add secure options for passing credentials via command-line ([#151](https://github.com/ManageIQ/floe/pull/151))
12
+ - Add a Docker Runner pull-policy option ([#155](https://github.com/ManageIQ/floe/pull/155))
13
+
14
+ ### Fixed
15
+ - Fix podman with empty output ([#150](https://github.com/ManageIQ/floe/pull/150))
16
+ - Fix run_container logger saying docker when using podman ([#154](https://github.com/ManageIQ/floe/pull/154))
17
+ - Ensure that workflow credentials is not-nil ([#156](https://github.com/ManageIQ/floe/pull/156))
18
+
19
+ ## [0.7.0] - 2023-12-18
20
+ ### Changed
21
+ - Remove the dependency on more_core_extensions in ReferencePath ([#144](https://github.com/ManageIQ/floe/pull/144))
22
+
23
+ ### Added
24
+ - Implement `ReferencePath#get` ([#144](https://github.com/ManageIQ/floe/pull/144))
25
+ - Allow a State to set a value in Credentials for subsequent states ([#145](https://github.com/ManageIQ/floe/pull/145))
26
+
7
27
  ## [0.6.1] - 2023-11-21
8
28
  ### Fixed
9
29
  - Return an error payload if run_async! fails ([#143](https://github.com/ManageIQ/floe/pull/143))
@@ -106,7 +126,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
106
126
  ### Added
107
127
  - Initial release
108
128
 
109
- [Unreleased]: https://github.com/ManageIQ/floe/compare/v0.6.1...HEAD
129
+ [Unreleased]: https://github.com/ManageIQ/floe/compare/v0.8.0...HEAD
130
+ [0.8.0]: https://github.com/ManageIQ/floe/compare/v0.7.0...v0.8.0
131
+ [0.7.0]: https://github.com/ManageIQ/floe/compare/v0.6.1...v0.7.0
110
132
  [0.6.1]: https://github.com/ManageIQ/floe/compare/v0.6.0...v0.6.1
111
133
  [0.6.0]: https://github.com/ManageIQ/floe/compare/v0.5.0...v0.6.0
112
134
  [0.5.0]: https://github.com/ManageIQ/floe/compare/v0.4.1...v0.5.0
data/README.md CHANGED
@@ -51,6 +51,48 @@ 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
+ Or if you are running the floe command programmatically you can securely provide the credentials via a stdin pipe via `--credentials=-`:
55
+ ```
56
+ echo '{"roleArn": "arn:aws:iam::111122223333:role/LambdaRole"}' | bundle exec ruby exe/floe --workflow my-workflow.asl --credentials -
57
+ ```
58
+
59
+ Or you can pass a file path with the `--credentials-file` parameter:
60
+ ```
61
+ bundle exec ruby exe/floe --workflow my-workflow.asl --credentials-file /tmp/20231218-80537-kj494t
62
+ ```
63
+
64
+ 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:
65
+
66
+ ```
67
+ bundle exec ruby exe/floe --workflow my-workflow.asl --credentials='{"username": "user", "password": "pass"}'
68
+ ```
69
+
70
+ ```json
71
+ {
72
+ "StartAt": "Login",
73
+ "States": {
74
+ "Login": {
75
+ "Type": "Task",
76
+ "Resource": "docker://login:latest",
77
+ "Credentials": {
78
+ "username.$": "$.username",
79
+ "password.$": "$.password"
80
+ },
81
+ "ResultPath": "$.Credentials",
82
+ "Next": "DoSomething"
83
+ },
84
+ "DoSomething": {
85
+ "Type": "Task",
86
+ "Resource": "docker://do-something:latest",
87
+ "Credentials": {
88
+ "token.$": "$.bearer_token"
89
+ },
90
+ "End": true
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
54
96
  ### Ruby Library
55
97
 
56
98
  ```ruby
@@ -120,6 +162,7 @@ end
120
162
  Options supported by the Docker docker runner are:
121
163
 
122
164
  * `network` - What docker to connect the container to, defaults to `"bridge"`. If you need access to host resources for development you can pass `network=host`.
165
+ * `pull-policy` - Pull image policy. The default is missing. Allowed values: always, missing, never
123
166
 
124
167
  #### Podman
125
168
 
@@ -129,6 +172,7 @@ Options supported by the podman docker runner are:
129
172
  * `log-level=string` - Log messages above specified level (trace, debug, info, warn, warning, error, fatal, panic)
130
173
  * `network=string` - What docker to connect the container to, defaults to `"bridge"`. If you need access to host resources for development you can pass `network=host`.
131
174
  * `noout=boolean` - do not output to stdout
175
+ * `pull-policy=string` - Pull image policy. The default is missing. Allowed values: always, missing, never, newer
132
176
  * `root=string` - Path to the root directory in which data, including images, is stored
133
177
  * `runroot=string` - Path to the 'run directory' where all state information is stored
134
178
  * `runtime=string` - Path to the OCI-compatible binary used to run containers
@@ -147,6 +191,7 @@ Options supported by the kubernetes docker runner are:
147
191
  * `kubeconfig` - Path to a kubeconfig file, defaults to `KUBECONFIG` environment variable or `~/.kube/config`
148
192
  * `kubeconfig_context` - Context to use in the kubeconfig file, defaults to `"default"`
149
193
  * `namespace` - Namespace to use when creating kubernetes resources, defaults to `"default"`
194
+ * `pull-policy` - Pull image policy. The default is Always. Allowed values: IfNotPresent, Always, Never
150
195
  * `server` - A kubernetes API Server URL, overrides anything in your kubeconfig file. If set `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` will be used
151
196
  * `token` - A bearer_token to use to authenticate to the kubernetes API, overrides anything in your kubeconfig file. If present, `/run/secrets/kubernetes.io/serviceaccount/token` will be used
152
197
  * `ca_file` - Path to a certificate-authority file for the kubernetes API, only valid if server and token are passed. If present `/run/secrets/kubernetes.io/serviceaccount/ca.crt` will be used
@@ -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/exe/floe CHANGED
@@ -6,15 +6,31 @@ require "optimist"
6
6
 
7
7
  opts = Optimist.options do
8
8
  version("v#{Floe::VERSION}\n")
9
- opt :workflow, "Path to your workflow json", :type => :string, :required => true
10
- opt :input, "JSON payload to input to the workflow", :default => '{}'
11
- opt :credentials, "JSON payload with credentials", :default => "{}"
12
- opt :docker_runner, "Type of runner for docker images", :default => "docker"
13
- opt :docker_runner_options, "Options to pass to the runner", :type => :strings
9
+ usage("[options] workflow input [workflow2 input2]")
10
+
11
+ opt :workflow, "Path to your workflow json (legacy)", :type => :string
12
+ opt :input, "JSON payload to input to the workflow (legacy)", :type => :string
13
+ opt :credentials, "JSON payload with credentials", :type => :string
14
+ opt :credentials_file, "Path to a file with credentials", :type => :string
15
+ opt :docker_runner, "Type of runner for docker images", :type => :string, :short => 'r'
16
+ opt :docker_runner_options, "Options to pass to the runner", :type => :strings, :short => 'o'
17
+
18
+ opt :docker, "Use docker to run images (short for --docker_runner=docker)", :type => :boolean
19
+ opt :podman, "Use podman to run images (short for --docker_runner=podman)", :type => :boolean
20
+ opt :kubernetes, "Use kubernetes to run images (short for --docker_runner=kubernetes)", :type => :boolean
14
21
  end
15
22
 
16
23
  Optimist.die(:docker_runner, "must be one of #{Floe::Workflow::Runner::TYPES.join(", ")}") unless Floe::Workflow::Runner::TYPES.include?(opts[:docker_runner])
17
24
 
25
+ # legacy support for --workflow
26
+ args = ARGV.empty? ? [opts[:workflow], opts[:input]] : ARGV
27
+ Optimist.die(:workflow, "must be specified") if args.empty?
28
+
29
+ # shortcut support
30
+ opts[:docker_runner] ||= "docker" if opts[:docker]
31
+ opts[:docker_runner] ||= "podman" if opts[:podman]
32
+ opts[:docker_runner] ||= "kubernetes" if opts[:kubernetes]
33
+
18
34
  require "logger"
19
35
  Floe.logger = Logger.new($stdout)
20
36
 
@@ -31,10 +47,36 @@ runner_options = opts[:docker_runner_options].to_h { |opt| opt.split("=", 2) }
31
47
 
32
48
  Floe::Workflow::Runner.docker_runner = runner_klass.new(runner_options)
33
49
 
34
- context = Floe::Workflow::Context.new(:input => opts[:input])
35
- workflow = Floe::Workflow.load(opts[:workflow], context, opts[:credentials])
50
+ credentials =
51
+ if opts[:credentials_given]
52
+ opts[:credentials] == "-" ? $stdin.read : opts[:credentials]
53
+ elsif opts[:credentials_file_given]
54
+ File.read(opts[:credentials_file])
55
+ end
56
+
57
+ workflows =
58
+ args.each_slice(2).map do |workflow, input|
59
+ context = Floe::Workflow::Context.new(:input => input || opts[:input] || "{}")
60
+ Floe::Workflow.load(workflow, context, credentials)
61
+ end
62
+
63
+ # run
64
+
65
+ outstanding = workflows.dup
66
+ until outstanding.empty?
67
+ ready = outstanding.select(&:step_nonblock_ready?)
68
+ ready.map(&:run_nonblock)
69
+ outstanding -= ready.select(&:end?)
70
+ sleep(1) if !outstanding.empty?
71
+ end
72
+
73
+ # display status
74
+
75
+ workflows.each do |workflow|
76
+ puts "", "#{workflow.name}#{" (#{workflow.status})" unless workflow.context.success?}", "===" if workflows.size > 1
77
+ puts workflow.output.inspect
78
+ end
36
79
 
37
- workflow.run!
80
+ # exit status
38
81
 
39
- puts workflow.output.inspect
40
- exit workflow.status == "success" ? 0 : 1
82
+ exit workflows.all? { |workflow| workflow.context.success? } ? 0 : 1
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.8.0".freeze
5
5
  end
@@ -74,6 +74,10 @@ module Floe
74
74
  end
75
75
  end
76
76
 
77
+ def success?
78
+ status == "success"
79
+ end
80
+
77
81
  def state=(val)
78
82
  @context["State"] = val
79
83
  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
@@ -14,7 +14,8 @@ module Floe
14
14
 
15
15
  super
16
16
 
17
- @network = options.fetch("network", "bridge")
17
+ @network = options.fetch("network", "bridge")
18
+ @pull_policy = options["pull-policy"]
18
19
  end
19
20
 
20
21
  def run_async!(resource, env = {}, secrets = {})
@@ -72,7 +73,7 @@ module Floe
72
73
  def run_container(image, env, secrets_file)
73
74
  params = run_container_params(image, env, secrets_file)
74
75
 
75
- logger.debug("Running #{AwesomeSpawn.build_command_line("docker", params)}")
76
+ logger.debug("Running #{AwesomeSpawn.build_command_line(self.class::DOCKER_COMMAND, params)}")
76
77
 
77
78
  result = docker!(*params)
78
79
  result.output
@@ -83,6 +84,7 @@ module Floe
83
84
  params << :detach
84
85
  params += env.map { |k, v| [:e, "#{k}=#{v}"] }
85
86
  params << [:e, "_CREDENTIALS=/run/secrets"] if secrets_file
87
+ params << [:pull, @pull_policy] if @pull_policy
86
88
  params << [:net, "host"] if @network == "host"
87
89
  params << [:v, "#{secrets_file}:/run/secrets:z"] if secrets_file
88
90
  params << [:name, container_name(image)]
@@ -40,6 +40,7 @@ module Floe
40
40
 
41
41
  @namespace = options.fetch("namespace", "default")
42
42
 
43
+ @pull_policy = options["pull-policy"]
43
44
  @task_service_account = options["task_service_account"]
44
45
 
45
46
  super
@@ -143,6 +144,7 @@ module Floe
143
144
  }
144
145
  }
145
146
 
147
+ spec[:spec][:imagePullPolicy] = @pull_policy if @pull_policy
146
148
  spec[:spec][:serviceAccountName] = @task_service_account if @task_service_account
147
149
 
148
150
  if secret
@@ -16,6 +16,7 @@ module Floe
16
16
  @log_level = options["log-level"]
17
17
  @network = options["network"]
18
18
  @noout = options["noout"].to_s == "true" if options.key?("noout")
19
+ @pull_policy = options["pull-policy"]
19
20
  @root = options["root"]
20
21
  @runroot = options["runroot"]
21
22
  @runtime = options["runtime"]
@@ -35,7 +36,8 @@ module Floe
35
36
  params << :detach
36
37
  params += env.map { |k, v| [:e, "#{k}=#{v}"] }
37
38
  params << [:e, "_CREDENTIALS=/run/secrets/#{secret}"] if secret
38
- params << [:net, "host"] if @network == "host"
39
+ params << [:pull, @pull_policy] if @pull_policy
40
+ params << [:net, "host"] if @network == "host"
39
41
  params << [:secret, secret] if secret
40
42
  params << [:name, container_name(image)]
41
43
  params << image
@@ -33,10 +33,6 @@ module Floe
33
33
  raise Floe::InvalidWorkflowError, "State name [#{name}] must be less than or equal to 80 characters" if name.length > 80
34
34
  end
35
35
 
36
- def run!(_input = nil)
37
- wait until run_nonblock! == 0
38
- end
39
-
40
36
  def wait(timeout: 5)
41
37
  start = Time.now.utc
42
38
 
@@ -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)
@@ -142,24 +137,14 @@ module Floe
142
137
  end
143
138
 
144
139
  def parse_output(output)
145
- return if output.nil?
146
140
  return output if output.kind_of?(Hash)
141
+ return if output.nil? || output.empty?
147
142
 
148
143
  JSON.parse(output.split("\n").last)
149
144
  rescue JSON::ParserError
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/workflow.rb CHANGED
@@ -8,9 +8,12 @@ module Floe
8
8
  include Logging
9
9
 
10
10
  class << self
11
- def load(path_or_io, context = nil, credentials = {})
11
+ def load(path_or_io, context = nil, credentials = {}, name = nil)
12
12
  payload = path_or_io.respond_to?(:read) ? path_or_io.read : File.read(path_or_io)
13
- new(payload, context, credentials)
13
+ # default the name if it is a filename and none was passed in
14
+ name ||= path_or_io.respond_to?(:read) ? "stream" : path_or_io.split("/").last.split(".").first
15
+
16
+ new(payload, context, credentials, name)
14
17
  end
15
18
 
16
19
  def wait(workflows, timeout: 5)
@@ -31,9 +34,9 @@ module Floe
31
34
  end
32
35
  end
33
36
 
34
- attr_reader :context, :credentials, :payload, :states, :states_by_name, :start_at
37
+ attr_reader :context, :credentials, :payload, :states, :states_by_name, :start_at, :name
35
38
 
36
- def initialize(payload, context = nil, credentials = {})
39
+ def initialize(payload, context = nil, credentials = {}, name = nil)
37
40
  payload = JSON.parse(payload) if payload.kind_of?(String)
38
41
  credentials = JSON.parse(credentials) if credentials.kind_of?(String)
39
42
  context = Context.new(context) unless context.kind_of?(Context)
@@ -42,12 +45,13 @@ module Floe
42
45
  raise Floe::InvalidWorkflowError, "Missing field \"StartAt\"" if payload["StartAt"].nil?
43
46
  raise Floe::InvalidWorkflowError, "\"StartAt\" not in the \"States\" field" unless payload["States"].key?(payload["StartAt"])
44
47
 
48
+ @name = name
45
49
  @payload = payload
46
50
  @context = context
47
- @credentials = credentials
51
+ @credentials = credentials || {}
48
52
  @start_at = payload["StartAt"]
49
53
 
50
- @states = payload["States"].to_a.map { |name, state| State.build!(self, name, state) }
54
+ @states = payload["States"].to_a.map { |state_name, state| State.build!(self, state_name, state) }
51
55
  @states_by_name = @states.each_with_object({}) { |state, result| result[state.name] = state }
52
56
 
53
57
  unless context.state.key?("Name")
@@ -58,16 +62,6 @@ module Floe
58
62
  raise Floe::InvalidWorkflowError, err.message
59
63
  end
60
64
 
61
- def run!
62
- step until end?
63
- self
64
- end
65
-
66
- def step
67
- step_nonblock_wait until step_nonblock == 0
68
- self
69
- end
70
-
71
65
  def run_nonblock
72
66
  loop while step_nonblock == 0 && !end?
73
67
  self
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.8.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: 2024-01-17 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