Is a custom trace tag possible with a st2 webhook? #3234

Open
pietervogelaar opened this Issue Feb 17, 2017 · 11 comments

Projects

None yet

3 participants

@pietervogelaar

I have implemented a rule and trigger and use the https://localhost/api/v1/webhooks/st2 for it as documented here: https://docs.stackstorm.com/webhooks.html#using-a-generic-webhook.

I'm trying to pass a trace tag, but it doesn't seem to work.

curl -s -D - -X POST https://example.com/api/v1/webhooks/st2 -H 'St2-Api-Key: ****' -H 'Content-Type: application/json' --data '{"trigger": "my_application.deploytrigger", "payload": { "repo_url": "ssh://git@bitbucket.org/example/myapp.git", "version": "0.2.2", "server_application": "orchestration", "server_role": "orchestrator", "server_environment": "prd", "target_dir": "/opt/applications/myapp", "pre_update_command": null, "pre_update_remote_command": null, "post_update_command": null, "post_update_remote_command": "/opt/applications/myapp/bin/install.sh" }, "trace_tag": "myapp-deploy-76" }'

What I see in the st2web UI is the trace tag "webhook-st2-32328981c2d241f9b8b94aeb9e425062".

Is a custom trace tag possible of what am I doing wrong?

@pietervogelaar

In addition, after this post the headers I get returned are:

HTTP/1.1 202 Accepted
Server: nginx/1.10.1
Date: Fri, 17 Feb 2017 11:10:55 GMT
Content-Type: application/json
Content-Length: 489
Connection: keep-alive
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Headers: Content-Type,Authorization,X-Auth-Token,St2-Api-Key,X-Request-ID
Access-Control-Expose-Headers: Content-Type,X-Limit,X-Total-Count,X-Request-ID
X-Request-ID: 174c32a6-5e17-40dd-afe4-8a5bb4ff7fee

The only reference I see is X-Request-ID: 174c32a6-5e17-40dd-afe4-8a5bb4ff7fee. But nothing like webhook-st2-32328981c2d241f9b8b94aeb9e425062. So how can I poll in an external system if StackStorm is finished with this particular trigger request?

@lakshmi-kannan
Contributor

@pietervogelaar You may pass St2-Trace-Tag header with your request. You may then use st2 trace get ${trace_ref} to track the request. Webhooks need not always result in executions because a rule may or may not match. st2 rule-enforcement list shows all "matched" rules that resulted in executions.

BTW St2-Trace-Tag is undocumented right now. If you want to help, please open a PR to add info about the header if it works. https://github.com/StackStorm/st2docs/blob/master/docs/source/webhooks.rst

@lakshmi-kannan lakshmi-kannan added this to the 2.2.1 milestone Feb 17, 2017
@lakshmi-kannan
Contributor

@LindsayHill Ahh, search failed me. Thanks!

@lakshmi-kannan
Contributor

BTW it is in traces documentation and not in webhooks documentation which might be a problem.

@pietervogelaar
pietervogelaar commented Feb 20, 2017 edited

A documentation reference from the webhook to the traces page would certainly be helpful. But I'm glad documentation is already available. I will try the St2-Trace-Tag header out, thanks!

@pietervogelaar

Thanks for the help, I have a working solution now with a python script in Jenkins. I still think it should be easier somehow to accomplish what I did here.

import json
import os
import requests
import sys
import time

api_url = os.environ['STACKSTORM_API_URL']
api_key = os.environ['STACKSTORM_API_KEY']
environment = os.environ['ENVIRONMENT']
version = os.environ['VERSION']
trace_tag = 'jenkins-{}-{}'.format(os.environ['JOB_NAME'], os.environ['BUILD_NUMBER'])
verbose = False

#--- Emitting deploy trigger
print "Trace tag: {}".format(trace_tag)
print "Emitting deploy trigger"
sys.stdout.flush()

headers = {
    'St2-Api-Key': api_key,
    'St2-Trace-Tag': trace_tag,
}

data = {
    'trigger': 'my_application.deploytrigger',
    'payload': {
        'repo_url': 'ssh://git@bitbucket.example.org/infra/myinfra.git',
        'version': version,
        'server_application': 'orchestration',
        'server_role': 'orchestrator',
        'server_environment': environment,
        'target_dir': '/opt/applications/myinfra',
        'pre_update_command': None,
        'pre_update_remote_command': None,
        'post_update_command': None,
        'post_update_remote_command': '/opt/applications/myinfra/bin/install.sh',
    }
}

response = requests.post('{}/api/v1/webhooks/st2'.format(api_url), headers=headers, json=data)
if verbose:
  print 'Response status code: {}'.format(response.status_code)
  print 'Response headers: {}'.format(response.headers)
  print 'Response content: {}'.format(response.text)

if response.status_code != requests.codes.accepted:
    print response.text
    exit(1)

sys.stdout.flush()
    
#--- Get corresponding action execution ID

# Try 10 times to get an action execution ID
for i in xrange(10):
    time.sleep(3)

    # Gets the action execution ID of the executed action caused by the trigger above
    headers = {'St2-Api-Key': api_key}
    payload = {'trace_tag': trace_tag}
    response = requests.get('{}/api/v1/traces'.format(api_url), headers=headers, params=payload)
    traces = response.json()

    if verbose:
      print "Action executions"
    
    action_execution_id = None
    if traces and 'action_executions' in traces[0]:
        if verbose:
            print traces[0]['action_executions']
        
        for action_execution in traces[0]['action_executions']:
            if action_execution['ref'] == 'my_application.deploy':
                action_execution_id = action_execution['object_id']
                break

    if action_execution_id is not None:
        break

print "Action execution ID: {}".format(action_execution_id)

#--- Executing status

print "Executing status:"
sys.stdout.flush()

# count
while True:    
    # Get the execution status
    headers = {'St2-Api-Key': api_key}
    payload = {'trace_tag': trace_tag}
    response = requests.get(
        '{}/api/v1/executions/{}'.format(api_url, action_execution_id),
        headers=headers,
        params=payload)

    print 'Running'
    sys.stdout.flush()

    execution = response.json()    
        
    if execution['status'] == 'succeeded':
        print 'Succeeded'
        exit(0)
    elif execution['status'] == 'failed':
        print 'Failed'
        exit(1)

    time.sleep(10)
@LindsayHill
Contributor
LindsayHill commented Feb 21, 2017 edited

If you want to always trigger the action from a remote system, then maybe you should use the API to execute an action, rather than use a webhook?

e.g.

curl -X POST -H  'Connection: keep-alive' -H  'Accept-Encoding: gzip, deflate' -H  'Accept: */*' -H  'User-Agent: python-requests/2.11.1' -H  'content-type: application/json' -H  'X-Auth-Token: 1987412384131357439534' -H  'Content-Length: 67' --data-binary '{"action": "core.local", "user": null, "parameters": {"cmd": "ls"}}' https://stackstormhost/api/v1/executions

You'll get an ID in the response, and you can then track the status of that execution ID.

@lakshmi-kannan
Contributor

@LindsayHill is right. You can use the executions API if you want a guaranteed execution and you don't really care about filtering based on the incoming payload. Sending a webhook and passing it through a rule is there to allow you to run executions based on some criteria evaluation.

Anyhow, if you want to use webhooks, you can query the traces API (See st2 --debug trace get ${trace_id} for API call example) and then use the response to see if there is any execution. Again, an execution is not always guaranteed because the criteria might fail in the rule for incoming payload. So you'll have to handle that case.

@pietervogelaar

@LindsayHill Ah okay, you're right. I thinks that's more what I was looking for. I guess I didn't think of it because I thought it wasn't possible. Because generally speaking, webhooks are the functionality to integrate external systems. Maybe is your suggestion/example input for enriching the documentation at https://docs.stackstorm.com/webhooks.html?

@LindsayHill
Contributor

Feel free to submit a PR to github.com/StackStorm/st2docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment