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

Allow a pack to specify Python 3 and have corresponding virtualenvs use Python 3 #3922

Closed
wants to merge 16 commits into from
Closed

Allow a pack to specify Python 3 and have corresponding virtualenvs use Python 3 #3922

wants to merge 16 commits into from

Conversation

tonybaloney
Copy link
Contributor

@tonybaloney tonybaloney commented Jan 1, 2018

As part of #3233 the pack (and/or) the user needs to be able to specify the minimum Python version required for the pack to operate.

In the case of Python 3, this requires another Python binary in the config.

This PR adds support for the st2common.virtualenv module to specify another Python binary path when building the env.

st2.conf now has a python3_binary setting to specify the default Python 3 binary path. This defaults to /usr/bin/python3 in both Ubuntu and Redhat. For newer versions of ubuntu, /usr/bin/python3 is a symlink to python3.5.

Python 3 has to be explicitly specified in the pack meta file.

If the user does not have a Python 3 binary installed it will fail on Pack Installation, virtualenv will raise an error.

https://github.com/StackStorm/st2/pull/3922/files#diff-4572714cfd795436cbea16dff51e3231R18

The configuration is such:

[actionrunner]
...
# Python binary which will be used by Python actions.
python_binary = /data/stanley/virtualenv/bin/python
python3_binary = /data/stanley/virtualenv/bin/python

The configuration of Python 2 binaries would default to the one running the script, but since this won't be the case in 3, it defaults again to /usr/bin/python3 https://github.com/StackStorm/st2/pull/3922/files#diff-f7f00f2d9fa85d6b39dc2def0f872561R222

pack.yaml now has a flag to specify the creation of the virtualenv using a Python 3 binary

system:
   python3: true

TODO :

  • write tests to check the integration
  • update pack.yaml meta template

Notes:

The dev Makefile now explicitly specifies python 2.7 in the virtual env. Some modern distributions will default to 3.x
https://github.com/StackStorm/st2/pull/3922/files#diff-b67911656ef5d18c4ae36cb6741b7965R273

There is now a switch to change the default Python version from 2 to 3. This is not configurable since it would likely break everything! https://github.com/StackStorm/st2/pull/3922/files#diff-1672fdd913c3ff338b3d0f9285d2fa81R59

Packs without meta files would not fail at the virtualenv stage, which is the same behaviour as before https://github.com/StackStorm/st2/pull/3922/files#diff-1672fdd913c3ff338b3d0f9285d2fa81R59

@tonybaloney
Copy link
Contributor Author

Just tested against a dev instance by:

  1. Cloning the libcloud pack
  2. Changing pack.yaml to have python3: true at the bottom
  3. Installing the pack from git
  4. Checking the Python version installed in the virtualenv
(virtualenv) ubuntu@ubuntu-xenial:~/st2$ /opt/stackstorm/virtualenvs/libcloud/bin/python --version
Python 3.5.2

@tonybaloney tonybaloney changed the title [WIP] Allow a pack (or the user) to specify the Python binary used in the VirtualEnv Allow a pack to specify Python 3 and have corresponding virtualenvs use Python 3 Jan 1, 2018
@Kami Kami self-assigned this Jan 1, 2018
@tonybaloney
Copy link
Contributor Author

Integration tested and added unit tests as well. This is now done.

@tonybaloney
Copy link
Contributor Author

@Kami It's all yours now 🎁


if has_pack_meta:
logger.debug('Checking pack specific Python version.')
if 'python3' in pack_meta.keys():
Copy link
Member

Choose a reason for hiding this comment

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

A while ago we added a couple more fields to the pack model and pack.yaml file, notably dependencies and system.

Perhaps it would be better to utilize system field instead of a top-level one (e.g. system.python3 = True or similar).

We also need to decide and clarify what that attribute really means - does it means that pack supports just Python 3 or that it supports Python 3 in addition to Python 3? And once we decide what it means and represents, we should document it :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed on the documentation. Top-level attribute seems off also, where is the meta file model? I couldn't find it anywhere.
Currently, it means that the pack should use a Python3 virtualenv. So it supports Python 3 at least, but shouldn't fall back to 2

Copy link
Member

Choose a reason for hiding this comment

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

We don't have a schema for system attribute yet, but you can add it and extend it here - https://github.com/StackStorm/st2/blob/master/st2common/st2common/models/api/pack.py#L135

For now, you can just add declaration for system.python3 attribute there under system field.

@@ -73,6 +74,19 @@ def setup_pack_virtualenv(pack_name, update=False, logger=None, include_pip=True
msg = 'Pack "%s" is not installed. Looked in: %s' % (pack_name, search_paths)
raise Exception(msg)

try:
pack_meta = get_pack_metadata(pack_path)
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps, for dependency injection and testing reasons, this function should take use_python3 as an argument instead of reading the metadata file itself.

Copy link
Member

Choose a reason for hiding this comment

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

Thinking out loud - I first thought this might slow down things quite a bit when running st2ctl register --register-setup-virtualenvs flag because we now also need to read and parse metadata file for each pack.

But after some more thought - we already need to do that, so another read and parse shouldn't add too much overhead since file should already be in filesystem cache. Future optimization would perhaps be to refactor the code a bit so we don't need to read and parse metadata file multiple times, but probably not needed right now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I assumed that the pack would still install if the meta-file wasn't in place, so I didn't want to alter the original behaviour

Copy link
Member

Choose a reason for hiding this comment

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

Metadata is mandatory so it would fail at some other step, but that's not really important here and I'm fine with the current approach.

I was mostly just "thinking out loud" about the potential performance overhead from reading and parsing pack metadata multiple times during install phase :)

@Kami
Copy link
Member

Kami commented Jan 1, 2018

Nice work 👍

@tonybaloney
Copy link
Contributor Author

Also @Kami is the meta model typed anywhere? It seems a bit shonky to just hardcode the dictionary keys into the virtualenv logic.

@tonybaloney
Copy link
Contributor Author

What do you want me to change? Move the flag to system?

@Kami
Copy link
Member

Kami commented Jan 3, 2018

Also @Kami is the meta model typed anywhere? It seems a bit shonky to just hardcode the dictionary keys into the virtualenv logic.

It's not, but we can / should add a schema for it.

@Kami
Copy link
Member

Kami commented Jan 3, 2018

Hopefully my clarification on the comments helped so we can move this forward :)

Another thing which would be nice to have is ability to "force" which Python version to use. The use case would be pack declaring system.python3 = True in metadata, but it turns out pack doesn't actually work completely or in part under Python 3.

Not a blocker right now and another way to approach that would be to "fix" that in the upstream pack, but at least the prerequisite for us merging "system.python3 = True` change for each pack should be that we run tests for that pack under Python 3.

@tonybaloney
Copy link
Contributor Author

@Kami moved the configuration to system.python3. will raise issue to fix st2-setup-tests and a PR for docs

@tonybaloney
Copy link
Contributor Author

@Kami I'm done with this one now. The build should pass now I've run make configgen on a dev installation and pushed the updates back

@Kami
Copy link
Member

Kami commented Jan 5, 2018

Also, just curious since I haven't done any Python 3 testing myself yet.

Actions are not fully self contained (same goes for sensors) and rely on some common StackStorm code which is only tested and works under Python 2.7.

I assume this could cause issues down the road so we should also add some basic StackStorm CI tests for a dummy / example python 3 pack which exercises all the "common" StackStorm code base, notably datastore functionality which is provided via action / sensor service.

@Kami
Copy link
Member

Kami commented Jan 5, 2018

After some more thought - as mentioned before, I think it would be much safer and better to start with and also add use_python3 or similar parameter to packs.install and packs.setup_virtualenv action. Then user could force python3 use by running st2 pack install --use-python3 or similar command.

This is much more forgiving than defaulting flag in metadata file to True3. If something doesn't work, user can simply re-install the pack omitting that flag. If there is some edge case and pack specifies system.python3 = True and the pack doesn't work (due to some bug in upstream code, st2 code or user environment), user would need to submit an upstream PR to the pack or hack / modify pack.yaml on disk. Neither of which is really desirable.

So in short, system.python3 attribute could be used to tell user that pack also works under Python 3, but user should still specify a parameter to packs.install / packs.setup_virtualenv to actually use Python 3 binary for that pack.

@Kami
Copy link
Member

Kami commented Jan 5, 2018

(from Slack)

kami [1:14 PM]
@anthonypjshaw #3922 (comment) sorry for getting back to that, but i'm just worried this could cause bad experience for our users
[1:14]
since our code and packs are not fully tested under python 3
[1:14]
and using the flag could cause a bad experience, while i think explicit opt-in approach is better
[1:14]
we could still utilize this flag as "signaling" user that this pack also works with python 3
[1:14]
but it should be explicit opt-in
[1:15]
and eventually, when we also test more of the stackstorm code base and packs under python 3, we could perhaps do that
[1:17]
@anthonypjshaw if needed and / or wanted, and you agree on that approach, i can also take that over 🙂

@tonybaloney Let me know if you are find with that approach (explicit opt-in via action parameter and CLI flag, until we get the whole CI up and running, etc. system.python3 would just serve informational role, indicating to the user Python 3 is likely also supported by that pack, but user needs to explicit opt-in on install).

If you are fine with that approach, I can make those changes.

@tonybaloney
Copy link
Contributor Author

@Kami in all the scenarios I’m thinking of, it’s the pack author who chooses whether the pack and the actions require Python 3. This could be for a number of reasons, like a package that won’t install in Python 2 (there are more and more of those now) or they used the Python 3 standard library namespaces. Or they wanted to stick to the Python 3 string idioms.
I would also assume the pack author is more aware and more technical than the one installing the pack. Agreed that the testing process needs to change- the pack unit tests need to run under Python 3 where it has been specified. Also, the subset of modules that are shared should also be run under 3 to check regressions.
As an example I have packs where I’ve had to deal with Unicode inbound and encoding which I would clean up in a Python 3 action. That code would not be backward compatible with 2 and the user would not know that either.

@Kami
Copy link
Member

Kami commented Jan 8, 2018

See #3929 (comment) for somewhat related issue.

I don't feel comfortable merging this with a lot better and more complete test coverage. I'm just worried that without a complete end to end test coverage, it will just represent a liability for us and cause a bad experience and pain for us and users who will try to use it.

In general I think it's better user experience if something is not supported than having something somewhat supported, but then things break and there are many edge cases when trying to use it. That will just frustrate most of the "typical" users (there are of course more technical users who like challenges and fixing things like that, but those are far and between).

@tonybaloney
Copy link
Contributor Author

Considering the amount of effort and changes in better testing Python 3 in core libraries what is the new status of this PR ? @Kami @LindsayHill

@Kami
Copy link
Member

Kami commented Feb 1, 2018

Sorry, didn't have time to dig in yet and take it across the finish line.

Sadly this PR is just a small part of much bigger change to get it into "fully done" state - first I need to figure out how to finalize this PR so everyone will be happy, then documentation, then hooking it up against StackStorm Exchange CI to make sure tests correctly use Python 3 when needed, etc.

But as far as you original question goes - it will still take some time to get everything running under Python 3 and even when that is the case, we will probably still need change like that to allow users to run Python runner actions under different version of Python (e.g. 3 when platform is using 2 and also vice versa).

@m4dcoder
Copy link
Contributor

@Kami What's the plan for this PR?

@brainstorm
Copy link

It would be rad to have it in place, today I was trying to have ansible 2.5.0rc1 and python3 but failed and found this PR... I think I'll just create a virtualenv with py3 manually for now, but it would be great to have it in, keep the good work @Kami!

@Kami
Copy link
Member

Kami commented Feb 26, 2018

@brainstorm It's actually @tonybaloney who did the most work on this PR :)

And yeah, manually creating a virtualenv using python3 binary should work for now.

Last time we couldn't come up with a compromise on how to make this work in a robust and straight forward manner and get it merged.

Perhaps a good middle of the ground approach would be to just add use_python3 (or similar) parameter to pack install action and CLI command. This way it would be opt-in and allow and easy way for user to switch back in case there are issues with Python 3.

What do others think?

@Kami
Copy link
Member

Kami commented Apr 10, 2018

Closing - continuation in #4076.

Hopefully we can resolve some of those issues which were uncovered yesterday and get it shipped in v2.8.0.

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

Successfully merging this pull request may close these issues.

4 participants