-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
32b1b3a
commit 02fb874
Showing
7 changed files
with
353 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
# Intermediate Parameters | ||
|
||
> v3.3 and after | ||
Traditionally, Argo workflows has supported input parameters from UI only when the workflow starts, | ||
and after that, it's pretty much on auto pilot. But, there are a lot of use cases where human interaction is required. | ||
|
||
This interaction is in the form of providing input text in the middle of the workflow, choosing from a dropdown of the options which a workflow step itself is intelligently generating. | ||
|
||
A similar feature which you can see in jenkins is [pipeline-input-step](https://www.jenkins.io/doc/pipeline/steps/pipeline-input-step/) | ||
|
||
Example use cases include: | ||
- A human approval before doing something in production environment. | ||
- Programatic generation of a list of inputs from which the user chooses. | ||
Choosing from a list of available databases which the workflow itself is generating. | ||
|
||
This feature is achieved via `suspend template`. | ||
|
||
The workflow will pause at a `Suspend` node, and user will be able to update parameters using fields type text or dropdown. | ||
|
||
## Intermediate Parameters Approval Example | ||
|
||
- The below example shows static enum values `approval` step. | ||
- The user will be able to choose between `[YES, NO]` which will be used in subsequent steps. | ||
|
||
[![Approval Example Demo](https://img.youtube.com/vi/eyeZ2oddwWE/0.jpg)](https://youtu.be/eyeZ2oddwWE) | ||
|
||
```yaml | ||
|
||
entrypoint: cicd-pipeline | ||
templates: | ||
- name: cicd-pipeline | ||
steps: | ||
- - name: deploy-pre-prod | ||
template: deploy | ||
- - name: approval | ||
template: approval | ||
- - name: deploy-prod | ||
template: deploy | ||
when: '{{steps.approval.outputs.parameters.approve}} == YES' | ||
- name: approval | ||
suspend: {} | ||
inputs: | ||
parameters: | ||
- name: approve | ||
default: 'NO' | ||
enum: | ||
- 'YES' | ||
- 'NO' | ||
outputs: | ||
parameters: | ||
- name: approve | ||
valueFrom: | ||
supplied: {} | ||
- name: deploy | ||
container: | ||
image: 'argoproj/argosay:v2' | ||
command: | ||
- /argosay | ||
args: | ||
- echo | ||
- deploying | ||
``` | ||
## Intermediate Parameters DB Schema Update Example | ||
- The below example shows programatic generation of `enum` values. | ||
- The `generate-db-list` template generates an output called `db_list`. | ||
- This output is of type `json`. | ||
- Since this `json` has a `key` called `enum`, with an array of options, the UI will parse this and display it as a dropdown. | ||
- The output can be any string also, in which case the UI will display it as a text field. Which the user can later edit. | ||
|
||
[![DB Schema Update Example Demo](https://img.youtube.com/vi/QgE-1782YJc/0.jpg)](https://youtu.be/QgE-1782YJc) | ||
|
||
```yaml | ||
entrypoint: db-schema-update | ||
templates: | ||
- name: db-schema-update | ||
steps: | ||
- - name: generate-db-list | ||
template: generate-db-list | ||
- - name: choose-db | ||
template: choose-db | ||
arguments: | ||
parameters: | ||
- name: db_name | ||
value: '{{steps.generate-db-list.outputs.parameters.db_list}}' | ||
- - name: update-schema | ||
template: update-schema | ||
arguments: | ||
parameters: | ||
- name: db_name | ||
value: '{{steps.choose-db.outputs.parameters.db_name}}' | ||
- name: generate-db-list | ||
outputs: | ||
parameters: | ||
- name: db_list | ||
valueFrom: | ||
path: /tmp/db_list.txt | ||
container: | ||
name: main | ||
image: 'argoproj/argosay:v2' | ||
command: | ||
- sh | ||
- '-c' | ||
args: | ||
- >- | ||
echo "{\"enum\": [\"db1\", \"db2\", \"db3\"]}" | tee /tmp/db_list.txt | ||
- name: choose-db | ||
inputs: | ||
parameters: | ||
- name: db_name | ||
outputs: | ||
parameters: | ||
- name: db_name | ||
valueFrom: | ||
supplied: {} | ||
suspend: {} | ||
- name: update-schema | ||
inputs: | ||
parameters: | ||
- name: db_name | ||
container: | ||
name: main | ||
image: 'argoproj/argosay:v2' | ||
command: | ||
- sh | ||
- '-c' | ||
args: | ||
- echo Updating DB {{inputs.parameters.db_name}} | ||
``` | ||
|
||
### Some Important Details | ||
- The suspend node should have the **SAME** parameters defined in `inputs.parameters` and `outputs.parameters`. | ||
- All the output parameters in the suspended node should have `valueFrom.supplied: {}` | ||
- The selected values will be available at `<SUSPENDED_NODE>.outputs.parameters.<PARAMETER_NAME>` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
ui/src/app/workflows/components/workflow-details/suspend-inputs.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import {Select} from 'argo-ui'; | ||
import * as React from 'react'; | ||
import {Parameter} from '../../../../models'; | ||
|
||
interface SuspendInputProps { | ||
parameters: Parameter[]; | ||
nodeId: string; | ||
setParameter: (key: string, value: string) => void; | ||
} | ||
|
||
export const SuspendInputs = (props: SuspendInputProps) => { | ||
const [parameters, setParameters] = React.useState(props.parameters); | ||
|
||
const setParameter = (key: string, value: string) => { | ||
props.setParameter(key, value); | ||
setParameters(previous => { | ||
return previous.map(param => { | ||
if (param.name === key) { | ||
param.value = value; | ||
} | ||
return param; | ||
}); | ||
}); | ||
}; | ||
|
||
const renderSelectField = (parameter: Parameter) => { | ||
return ( | ||
<React.Fragment key={parameter.name}> | ||
<br /> | ||
<label>{parameter.name}</label> | ||
<Select | ||
value={parameter.value || parameter.default} | ||
options={parameter.enum.map(value => ({ | ||
value, | ||
title: value | ||
}))} | ||
onChange={selected => setParameter(parameter.name, selected.value)} | ||
/> | ||
</React.Fragment> | ||
); | ||
}; | ||
|
||
const renderInputField = (parameter: Parameter) => { | ||
return ( | ||
<React.Fragment key={parameter.name}> | ||
<br /> | ||
<label>{parameter.name}</label> | ||
<input className='argo-field' defaultValue={parameter.value || parameter.default} onChange={event => setParameter(parameter.name, event.target.value)} /> | ||
</React.Fragment> | ||
); | ||
}; | ||
|
||
const renderFields = (parameter: Parameter) => { | ||
if (parameter.enum) { | ||
return renderSelectField(parameter); | ||
} | ||
return renderInputField(parameter); | ||
}; | ||
|
||
const renderInputContentIfApplicable = () => { | ||
if (parameters.length === 0) { | ||
return <React.Fragment />; | ||
} | ||
return ( | ||
<React.Fragment> | ||
<h2>Modify parameters</h2> | ||
{parameters.map(renderFields)} | ||
<br /> | ||
</React.Fragment> | ||
); | ||
}; | ||
|
||
return ( | ||
<div> | ||
{renderInputContentIfApplicable()} | ||
<br /> | ||
Are you sure you want to resume node {props.nodeId} ? | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.