October 31, 2017
by Matt Oswalt
StackStorm 2.5 introduces one of our most highly requested features: “Inquiries”. Inquiries are a way of “asking a question” in the middle of a workflow (Mistral or ActionChain), to get additional data before moving on.
For instance, while you can store service credentials in the StackStorm datastore and retrieve them using a Jinja snippet, some services require two-factor authentication. It’s necessary, therefore, to be able to pause the workflow at a certain point, and allow a human to “inject” this data into the workflow midstream. There are a number of other use cases for this functionality, including the simple “I’m about to do something stupid dangerous, should I proceed?”.
Before we get into Inquiries and how they work, an important note: we’ve been working hard on making sure the new feature is useful for a variety of use cases, and as robust as possible. However, it is a complex and fairly low-level feature that has a lot of moving parts, and before recommending it for production use, we’d like to spend a release cycle gathering feedback on the API and the user experience. So, for 2.5, we would love for you to use this feature in your test/dev deployments of StackStorm and let us know what you think. Don’t worry, this is not going to stay “alpha” forever! We expect that it will be “production ready” in StackStorm 2.6, due to ship later this year.
In order to make use of Inquiries in a workflow, we’re introducing a new action: “core.ask”. In order to “ask a question” in your workflow, simply use this action where you would like this question to be asked.
The “core.ask” action supports a number of parameters, but the most important one by far is the ”schema” parameter. This parameter defines exactly what kind of responses will satisfy the Inquiry, and allow the workflow to continue. When users respond to this Inquiry, the response data that gets sent to the StackStorm API must validate against this schema in order to satisfy the Inquiry and allow the workflow to continue. It sounds a bit complicated, but don’t worry, the “st2” client makes it easy to put together a valid response. We’ll walk through that soon.
Here’s a simple ActionChain that uses “core.ask” to ask for a second-factor authentication parameter using “core.ask”:
chain: - name: task1 ref: core.ask params: route: developers schema: type: object properties: secondfactor: type: string description: Please enter second factor for authenticating to "foo" service required: True on-success: "task2" - name: task2 ref: core.local params: cmd: echo "We can now authenticate to "foo" service with {{ task1.result.response.secondfactor }}"
Executing this workflow results in a “pending” status for “task1”, and the ActionChain itself is “paused”.
~$ st2 run examples.chain-test-inquiry . id: 59d1ecb632ed353f1f340898 action.ref: examples.chain-test-inquiry parameters: None status: paused result_task: task1 result: roles: [] route: developers schema: properties: secondfactor: description: Please enter second factor for authenticating to "foo" service required: true type: string type: object ttl: 1440 users: [] start_timestamp: 2017-10-02T07:37:26.854217Z end_timestamp: None +--------------------------+---------+-------+----------+-------------------------------+ | id | status | task | action | start_timestamp | +--------------------------+---------+-------+----------+-------------------------------+ | 59d1ecb732ed353ec4aa9a5a | pending | task1 | core.ask | Mon, 02 Oct 2017 07:37:27 UTC | +--------------------------+---------+-------+----------+-------------------------------+
The workflow will remain paused until a response is received that validates against the provided schema.
A new subcommand: “st2 inquiry” has been added to the StackStorm CLI. Using this, you can “list” existing Inquiries, “get” a specific Inquiry, or “respond” to an Inquiry.
“st2 inquiry list” shows a summary of existing Inquiries:
~$ st2 inquiry list +--------------------------+-------+-------+------------+------+ | id | roles | users | route | ttl | +--------------------------+-------+-------+------------+------+ | 59d1ecb732ed353ec4aa9a5a | | | developers | 1440 | +--------------------------+-------+-------+------------+------+
Like most other resources in StackStorm, we can use the get
subcommand to retrieve details about this Inquiry, using its ID provided in the previous output:
~$ st2 inquiry get 59d1ecb732ed353ec4aa9a5a +----------+--------------------------------------------------------------+ | Property | Value | +----------+--------------------------------------------------------------+ | id | 59d1ecb732ed353ec4aa9a5a | | roles | | | users | | | route | developers | | ttl | 1440 | | schema | { | | | "type": "object", | | | "properties": { | | | "secondfactor": { | | | "required": true, | | | "type": "string", | | | "description": "Please enter second factor for | | | authenticating to "foo" service" | | | } | | | } | | | } | +----------+--------------------------------------------------------------+
Since the schema is included in the Inquiry details, the client knows what kind of data is required to formulate a valid response. The “st2 respond” command will step through each of the properties in the schema, prompting you with the text in the “description” field for each property:
~$ st2 inquiry respond 59d1ecb732ed353ec4aa9a5a secondfactor: bar Please enter second factor for authenticating to "foo" service Response accepted. Successful response data to follow... +----------+---------------------------+ | Property | Value | +----------+---------------------------+ | id | 59d1ecb732ed353ec4aa9a5a | | response | { | | | "secondfactor": "bar" | | | } | +----------+---------------------------+
If the response is accepted, the valid response payload will be printed to the screen, and the workflow that initially raised the Inquiry will continue. Note that the workflow we showed in the previous example now shows both tasks executed, and marked with a “succeeded” status:
~$ st2 execution get 59d1ecb632ed353f1f340898 id: 59d1ecb632ed353f1f340898 action.ref: examples.chain-test-inquiry parameters: None status: succeeded (468s elapsed) result_task: task2 result: failed: false return_code: 0 stderr: '' stdout: We can now authenticate to foo service with bar succeeded: true start_timestamp: 2017-10-02T07:37:26.854217Z end_timestamp: 2017-10-02T07:45:14.123405Z +--------------------------+------------------------+-------+------------+-------------------------------+ | id | status | task | action | start_timestamp | +--------------------------+------------------------+-------+------------+-------------------------------+ | 59d1ecb732ed353ec4aa9a5a | succeeded (0s elapsed) | task1 | core.ask | Mon, 02 Oct 2017 07:37:27 UTC | | 59d1ee8932ed353ec4aa9a5d | succeeded (1s elapsed) | task2 | core.local | Mon, 02 Oct 2017 07:45:12 UTC | +--------------------------+------------------------+-------+------------+-------------------------------+
Also notice that the output for this workflow contains the value we passed in to the response, “bar”. You can use the same method to pass a specific field in the response payload to another action.
This was a very light introduction to Inquiries. Please see the Inquiries documentation for more information on:
We’re excited to finally release this functionality to you, and we look forward to gathering your feedback on Inquiries. We have a lot more planned that will build on top of this functionality (like tighter Chatops integration with Inquiries) and we want to make sure we get this right. So, get inquiring!