Workflow variable comparison

I am new to Stackstorm, Orquesta, YAML, pretty much all of it. I have been tasked with creating a workflow which will check the available drive space of remote machines, clean up targetted files, and exiting. I’ve figured out the part of getting the drive space availability, but am now trying to come up with an action (using core.noop) that will determine the result of the previous action (getting the drive space) and compare it to a predefined amount. In the action where I gather the value, I am publishing the result to a variable called “availablediskspace”. By looking at other examples I’ve found out in the ether, I thought maybe the following would work:

action: core.noop
next:

  • when: <% availablediskspace <= 15 %>
    do: nextaction

The workflow fails and the output I get is:

“YaqlEvaluationException: Unable to evaluate expression ‘<% availablediskspace <= 15 %>’. NoMatchingFunctionException: No function “#operator_<=” matches supplied arguments”,

I’m not sure if the issue is that ‘availablediskspace’ isn’t seen as an integer (which brings up another question as to how I cast that as an integer for this purpose), or if you really can’t do things like this. Any help would be greatly appreciated.

TIA

You need to reference the global context to check that variable. Your syntax is not correct and it should be:

when <% ctx(availablediskspace) <= 15 %>

or

when <% ctx().availablediskspace <= 15 %>

1 Like

Thank you jamesdreid. I tried both, but I still get the same error. It make me wonder if the data in availablediskspace is being cast as a string instead of an int. Is there a way to specifically cast a variable as an int in Yaql?

Sure…

when <% int(ctx().availablediskspace) <= 15 %>
1 Like

Unfortunately that didn’t help. I guess I should provide a bit more details. The value of availablediskspace comes from the result of a bash command on a remote machine.

The specific command I’m running is echo $((100 - (df -h / | grep -Eo "[0-9]+[BKMGT%] " | tail -1 | grep -Eo "[0-9]+")))

I do really appreciate all of your help so far, this is all new to me and I’m not finding too much helpful documentation for Stackstorm or YAQL expressions which address my specific situation, or even remotely close to my situation.

The error being generated is the same I see on http://yaqluator.com/ when trying to compare the string ‘15’ to the int 15.

'15'>=15

That generates the error: Exception evaluating YAQL expression:

No function "#operator_>=" matches supplied arguments

The the int() function above applied to the ‘15’ string I suggested above corrects this.

int('15') >= 15

You can try adding a core.echo into the workflow and have it output the variables to see if you are getting data returned that you are not expecting, but it appears at this point that maybe your “availablediskspace” is not getting set to what you expect and it is not an integer or even something that can be converted to an integer.

1 Like

The latter part of your last statement appears to be the case, meaning I may have to move to utilizing a Python script instead of core.remote to grab the data so I can actually cast the data specifically into an integer. What I get when I try to cast to int in the workflow, it gives me a YaqlEvaluationException saying it can’t change from a ‘FrozenDict’. Thank you for all of your help, it has definitely helped me understand all of this a little better.

I don’t think the workflow is failing due to the use of a core.remote command. It seems like you are not publishing your variable correctly. The following simple workflow uses the core.local command to execute your df command on my local ST2 server, then sets the results to a variable that is used in a YAQL comparison like you have attempted.

version: 1.0
tasks:
  # 
  task1:
    action: core.local
    input:
      cmd: " echo $((100 - $(df -h / | grep -Eo \"[0-9]+[BKMGT%] \" | tail -1 | grep -Eo \"[0-9]+\")))"
    next:
      - do:
          - task2
        when: <% succeeded() %>
        publish:
          - availablediskspace: <% result().stdout %>
  # [342, 437]
  task2:
    action: core.noop
    next:
      - do:
          - task3
        when: <% int(ctx(availablediskspace)) <= 50 %>
  # 
  task3:
    action: core.echo
    input:
      message: Greater
vars:
  - availablediskspace: null

If I have to guess, you have set the variable incorrectly and may be setting it to <% result() %> but the output data you want is actually what is included in “stdout”. I did not use core.remote but my guess is yo want to try using my publish to set your variable for further comparison:

availablediskspace: <% result().stdout %>
1 Like

It most definitely works if I change the action context to core.local, but does not work when attempting to use core.remote.

That gives to following error:
“YaqlEvaluationException: Unable to resolve key ‘stdout’ in expression ‘<% result().stdout %>’ from context.”

Looks like the core.remote supports multiple hosts as input and therefore returns the results for each host as a separate dictionary in the results. Therefore, you need to modify the publish slightly to extract the correct data. The following workflow should work with the core.remote command using a single host. Obviously, there will be a lot more logic to resolve if you plan on running this workflow on multiple hosts, but this should at least get the basic workflow going:

version: 1.0
tasks:
  task2:
    action: core.noop
    next:
      - do:
          - task3
        when: <% int(ctx(availablediskspace)) >= 50 %>
  task3:
    action: core.echo
    input:
      message: Greater
  task4:
    action: core.remote
    input:
      cmd: " echo $((100 - $(df -h / | grep -Eo \"[0-9]+[BKMGT%] \" | tail -1 | grep -Eo \"[0-9]+\")))"
      hosts: 1.1.1.1
      password: X*X*X*X*X*X*X*X*X*X*X*X
      username: username
    next:
      - do:
          - task2
        publish:
          - availablediskspace: " <% result()['1.1.1.1']['stdout'] %>"
        when: succeeded()
vars:
  - availablediskspace: null

The big change is to the publish statement in Task4 where you have to go one level deeper into the result data to get the results:

 - availablediskspace: " <% result()['1.1.1.1']['stdout'] %>"
1 Like

You sir, are a genius! That has totally resolved my issue. Thank you so much for your continued support and handholding. :slight_smile: I appreciate all of your help so much.