Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor chatops to process input alias matching server side #2895

Merged
merged 66 commits into from Sep 15, 2016
Merged

Refactor chatops to process input alias matching server side #2895

merged 66 commits into from Sep 15, 2016

Conversation

tonybaloney
Copy link
Contributor

@tonybaloney tonybaloney commented Sep 12, 2016

This PR is proposing to allow clients to submit text captured via another method (e.g. Python bot or direct input) into the StackStorm chatops system. To cater for this, StackStorm needs to be changed to:

  • Move the business logic of flattening action alias format strings into regex patterns into an API controller
  • Move the matching logic from hubot-stackstorm into a server-side controller

Strategy:

  • Create a utility submodule in st2common.util for the alias matching/regex logic
  • Create a series of test scenarios for checking regex logic in the re stdlib compared with the existing hubot code.
  • Create an API action for matching a text input from a chatops window to an alias/action reference
  • Create a helper function on the st2client project, e.g. st2 alias match "honk-honk"

Functionality in future PRs:

  • Create an API view for formatted alias patterns
  • Create an API view for showing help strings of aliases
  • Modify the st2stream API to support server side filtering (not required but preferred).

This is a collaboration with @nzlosh

@estee-tew
Copy link

@nzlosh
Copy link
Contributor

nzlosh commented Sep 12, 2016

@estee-tew I don't have access to the url you posted. Would you be able to share the comments here?

@emedvedev
Copy link
Contributor

This is amazing and long due; one of our chatops roadmap items, actually.

The regex is already built here on the back-end: https://github.com/StackStorm/st2/blob/c013fc72111ae9141b5c474f32ec85dae3660498/st2common/st2common/models/utils/action_alias_utils.py
You should be able to make it give you a full list of compiled regexes mapped to aliases without much effort. Overall, the plan looks solid. ❤️

@enykeev
Copy link
Member

enykeev commented Sep 12, 2016

LOG = logging.getLogger(__name__)


class ChatopsController(resource.ContentPackResourceController):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opinions here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to keep those methods / operations on the alias controller?

The reason is that right now StackStorm concept is called action alias and the code doesn't use "ChatOps" term anywhere else (afaik) so it might be a bit confusing to call it ChatOps here...

@Kami
Copy link
Member

Kami commented Sep 12, 2016

Nice, indeed!

That's been our goal for a while now, but we never got to it. Moving all the parsing and matching to the server will allow user to make clients a lot thinner / dumb which should make it easier to develop clients for other protocols and also reduce the client maintenance burden.

Well, at least the basic implementation. For performance reasons, in some scenarios (a lot of messages per second and a lot of aliases) it might make sense to move some pre-parsing / matching to the client.

@estee-tew
Copy link

@tonybaloney
Copy link
Contributor Author

done.

@@ -58,6 +73,37 @@ def get_all(self, **kwargs):
def get_one(self, ref_or_id):
return super(ActionAliasController, self)._get_one(ref_or_id)

@jsexpose(arg_types=[str], status_code=http_client.ACCEPTED)
def match(self, command, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can user also pass other arguments to this function? If not, we should probably get rid of **kwargs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they could for the purposes of reducing the criteria of the underlying get_all call, which is where they are passed. So filtering by pack for example.


action_exec_mgr = self.app.client.managers['ActionAliasExecution']

execution = action_exec_mgr.create(execution, **kwargs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, much better 👍

def match(self, command, **kwargs):
url = '/%s/match' % self.resource.get_url_path_name()
query_str = urlencode({'command': command})
response = self.client.post_raw(url, query_str, **kwargs)
Copy link
Member

@Kami Kami Sep 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this is sent as query string, right?

If so, requests library should encode it correctly as long as the requests.post method is called with the params=params argument.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't 100% clear on the docs (I can't stand that documentation!). I know this works now :-)

@Kami
Copy link
Member

Kami commented Sep 15, 2016

Nice, thanks, LGTM!

I will check it out and play a bit with it locally and if everything looks good merge it into master.

@@ -48,6 +52,17 @@ class ActionAliasController(resource.ContentPackResourceController):
'sort': ['pack', 'name']
}

_custom_actions = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, it appears _custom_actions is only supported in newer versions of pecan because I get 404 in execute :/

We still use 0.7.0 because of backward incompatible changes in newer versions which make it hassle to upgrade.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it looks like old versions support it as well. Must be something else - looking into it.

@@ -48,6 +52,17 @@ class ActionAliasController(resource.ContentPackResourceController):
'sort': ['pack', 'name']
}

_custom_actions = {
Copy link
Member

@Kami Kami Sep 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it's a CLI issue - CLI doesn't correctly send query param to the method...

(virtualenv)vagrant@vagrant-ubuntu-trusty-64:/data/stanley$ python ./st2client/st2client/shell.py action-alias match "foo bar foo"
ERROR: 404 Client Error: Not Found
MESSAGE: The resource could not be found. for url: http://127.0.0.1:9101/v1/actionalias/m
match() takes exactly 2 arguments (1 given)

I will make urlencode and requests changes mentioned below, I believe this should fix it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, since this is a post we should probably send data as body and not via query string.

This way it will be consistent with other models. Yes, it's a bit "heavy" and we need a wrapper API model, but we already do that in other places.

I will make that change, hope you don't mind :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There we go - 4afaa54

It works now, woo!

(virtualenv)vagrant@vagrant-ubuntu-trusty-64:/data/stanley$ python ./st2client/st2client/shell.py action-alias match "run uptime on localhost"
2016-09-15 12:37:32,670  WARNING - Auth API server is not available, skipping authentication.
+------------------+---------------------------------------------+
| name             | description                                 |
+------------------+---------------------------------------------+
| remote_shell_cmd | Execute a command on a remote host via SSH. |
+------------------+---------------------------------------------+
(virtualenv)vagrant@vagrant-ubuntu-trusty-64:/data/stanley$ python ./st2client/st2client/shell.py action-alias execute "run uptime on localhost"
2016-09-15 12:37:34,473  WARNING - Auth API server is not available, skipping authentication.
Started execution, id '57da960e0640fd107ab26409'
Hold tight while I run command: *uptime* on hosts *localhost*

Minor thing - what do other things, I think execute could be blocking by default (similar as st2 run command) and optionally user can specify --async flag to make it non-blocking. WDYT?


@resource.add_auth_token_to_kwargs_from_cli
def run(self, args, **kwargs):
action_alias, representation = self.manager.match(args.command_text, **kwargs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with having this command for now, but for true server side matching and execution which would allow us to make clients event dumber I think we should also move this to the server side (e.g. "match and execute" endpoint or similar).

This is not a blocker right now though. We can leave it here and introduce this new API endpoint in the future. The CLI command is forward compatible anyway (once the feature is available on the server, we just need to change the code here).

This would also save client / user one API call which is actually good in this case, especially if you send every single line posted to chat to the API.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should only send the lines that are addressed to Hubot, so that's not a huge concern, but match-and-execute would be pretty good regardless.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the patterns got a bit wonky crossing resource types between controllers. I'll have a think about it.

@estee-tew
Copy link

@Kami Kami merged commit 21a737a into StackStorm:master Sep 15, 2016
@Kami
Copy link
Member

Kami commented Sep 15, 2016

Merged into master via #2904.

Thanks again for great work and a PR! 👍

And in the future if you find yourself with nothing to do (yeah, I know, that never happens :D) it would be great if you could also look into this #2895 (comment).

@emedvedev
Copy link
Contributor

❤️ ❤️ ❤️
Awesome job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants