StackStorm / st2

StackStorm (aka "IFTTT for Ops") is event-driven automation for auto-remediation, incident responses, troubleshooting, deployments, and more for DevOps and SREs. Includes rules engine, workflow, 160 integration packs with 6000+ actions (see https://exchange.stackstorm.org) and ChatOps. Installer at https://docs.stackstorm.com/install/index.html
https://stackstorm.com/
Apache License 2.0
6.08k stars 747 forks source link

Incorrect JSON format #2608

Closed kiyology closed 8 years ago

kiyology commented 8 years ago

Hi,

I'm experiencing this issue when using stackstorm: Here's my action config:


---
description: Run a local linux command
enabled: true
entry_point: workflows/mistral-basic.yaml
name: mistral-basic
pack: examples
parameters:
  payload:
    required: true
    type: object
runner_type: mistral-v2

Here's my workflow config:

version: '2.0'

examples.mistral-basic:
    description: A basic workflow that runs an arbitrary linux command.
    type: direct
    input:
        - payload
    output:
        stdout: <% $.stdout %>
    tasks:
        task1:
            action: core.local cmd="node /opt/stackstorm/packs/examples/actions/yamas2-action/yamas2-action.js <% $.payload %>"
            publish:
                stdout: <% $.task1.stdout %>
                stderr: <% $.task1.stderr %>

Here's my rule config:


---
uid: 'rule:core:yamas2_action'
tags: []
type:
  ref: standard
  parameters:
enabled: true
name: yamas2_action
trigger:
  ref: core.88a53537-2989-41b8-9ec0-e23f7e75447c
  type: core.st2.webhook
  parameters:
    url: yamas2_listener2
criteria:
action:
  ref: examples.mistral-basic
  parameters:
    payload: '{{ trigger.body }}'
ref: core.yamas2_action
id: 57045099a8bf5911aa468d7d
pack: core

Basically I'm having a webhook and sends the payload received by the webhook to a mistral workflow action, which takes the payload as the third parameter. Everything works fine except that when it's executing, the double quotes inside payload JSON has been substituted by two single quotes which is causing my script to fail when parsing it as a JSON.

Here's the execution detail:

id: 57045246a8bf5911aa468d89
status: failed
parameters: 
  cmd: 'node /opt/stackstorm/packs/examples/actions/yamas2-action/yamas2-action.js {u''recovery_alerts'': 0, u''alerts'': [{u''status_code'': 1, u''tags'': {u''host'': u''pubs-yamas2-listener.halo.media.corp.bf1.com'', u''_threshold_name'': u''loadstone_hist'', u''hostgroup'': u''prod_ugeo_ls_all''}, u''timestamp'': 1455315900000000, u''text'': u''Data collection failure''}, {u''status_code'': 1, u''tags'': {u''host'': u''pubs-yamas2-listener.halo.media.corp.bf1.com'', u''_threshold_name'': u''lodestone'', u''hostgroup'': u''prod_ugeo_ls_all''}, u''timestamp'': 1455315900000000, u''text'': u''scoreboard file lodestone does not exist''}], u''namespace'': u''Geo'', u''bad_alerts'': 2}'
result: 
  failed: true
  return_code: 8
  stderr: "
undefined:1

And there's a character 'u' in front of all the beginning two single quotes of a string. I tried using payload as a string or object. If I use payload as a string, I don't get the character 'u', but all the double quotes are still replaced by two single quotes.

And idea why?

Thanks!

lakshmi-kannan commented 8 years ago

Sounds like an awful confusion regarding JSON representation. Do you parse the input as JSON string inside the yamas2-action.js file? Would you be able to show the code for that? I'll try to repro the situation locally and suggest an approach. Hang tight.

kiyology commented 8 years ago

Thanks for the reply! Yes, I'm parsing the input as JSON string inside yamas2-action.js file. The way I'm parsing it is payload = JSON.parse(process.argv[2]),

I printed it out the whole command through st2 execution get, the json string was being passed as an argument like {u''recovery_alerts'': . With single quotes and the charater 'u', the script was unable to parse it.

lakshmi-kannan commented 8 years ago

I reproed the issue on my box. It looks like things are working per design but don't work well for your use case. Let me explain.

trigger.body is sent as an object correctly to the workflow. So type of payload in the workflow is indeed an object. The problem is in the following line:

action: core.local cmd="node /opt/stackstorm/packs/examples/actions/yamas2-action/yamas2-action.js <% $.payload %>"

This is equivalent of you trying to pass an object in the command line which has no meaning. Unfortunately YAQL doesn't seem to support a toJSON method which we could have used to pass the actual string rep to the script which would then work. So your options at this point are to actually pass flattened parameters to the script instead of the object.

For example,

action: core.local cmd="node /opt/stackstorm/packs/examples/actions/yamas2-action/yamas2-action.js <% $.payload.get('param1') %> <% $.payload.get('param2') %>"

I hope the example I gave you makes sense. We'll see how to clear up the confusion in docs or something. You can also ping me on slack for more interactive help.

kiyology commented 8 years ago

Thanks for the detailed explanation! So if I want to use the whole json to the script (because I need many fields and passing them one by one through <% $.payload.get('param1') %> might not be efficient), I assume there's no proper way of doing this, right?

lakshmi-kannan commented 8 years ago

@kiyology I am not sure about proper but you could add another step in the mistral workflow that translates an object to a JSON string and then passes the string to next step in the workflow as input. LMK if this isn't clear and I can whip up an example. We talked a bit about supporting JSON transformations as first class YAQL function. We might add this in future releases but no promises there.

lakshmi-kannan commented 8 years ago

@kiyology Can I close this issue?

kiyology commented 8 years ago

Yes, thank you so much for your help! :)