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

python plugin: do the right thing with classic. #1093

Merged
merged 11 commits into from
Feb 3, 2017

Conversation

sergiusens
Copy link
Collaborator

To fully enable classic confinment for python based snaps, there are
two big things that need to get done; no env var leaking and
use a python interpreter with the classic compilation flags.

LP: #1657504

Signed-off-by: Sergio Schvezov sergio.schvezov@canonical.com

@adam-stokes
Copy link

Will this allow a successful installation of snaps on trusty as well?

@sergiusens sergiusens force-pushed the bugfix/classic-python-plugin branch 2 times, most recently from 494b754 to 57d7255 Compare January 30, 2017 17:24
@sergiusens
Copy link
Collaborator Author

@battlemidget yes; there is only one last thing for trusty support being tracked on https://bugs.launchpad.net/bugs/1657504

There is however one last issue involving core on comment https://bugs.launchpad.net/snapd/+bug/1657504/comments/15

For classic, you will need to provide an interpreter, a quick way is like

name: asciinema
version: '1.3.0'
summary: Record and share your terminal sessions, the right way.
description: |
  Forget screen recording apps and blurry video. Enjoy a lightweight,
  purely text-based approach to terminal recording.

grade: devel
confinement: classic

apps:
  asciinema:
    command: bin/asciinema

parts:
  asciinema:
    plugin: python
    python-packages: [$SNAPCRAFT_PROJECT_NAME==$SNAPCRAFT_PROJECT_VERSION]
    after: [python3]
  python3:
    source: https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz
    plugin: autotools
    configflags: [--prefix=/usr]
    build-packages: [libssl-dev]

# binaries are linked with `nodefaultlib` but we still do
# not want to leak PATH or other environment variables
# that would affect the applications view of the classic
# environment it is dropped into.
replace_path = r'{}/[a-z0-9][a-z0-9+-]*/install'.format(
self._parts_dir)
Copy link
Contributor

Choose a reason for hiding this comment

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

has _parts_dir been sanitized to not have regexpish things in it? otherwise you want re.escape(self._parts_dir) here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

it is sanitized but good idea

package_dir=self._python_package_dir, env=env,
extra_install_args=['--ignore-installed'])

if download:
pip.download(args)
pip.wheel(args)
# pip.wheel(args)
Copy link
Contributor

Choose a reason for hiding this comment

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

# leftover? Or ...?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah, already removed locally, didn't want to stress the weak infra ;-)

'$LD_LIBRARY_PATH\n')
if cwd:
f.write('{}\n'.format(cwd))
f.write('exec {} {}\n'.format(executable, args))
Copy link
Contributor

Choose a reason for hiding this comment

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

your use of f.write is entertaining :-)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I can change to print 😉

Copy link
Contributor

@kyrofa kyrofa left a comment

Choose a reason for hiding this comment

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

This looks mostly good to me. I'll be honest and say I'm not familiar with the site package fiddling we're doing here, but I looked into it and it seems sane. I have a few niggly comments, the bigger one is the shutil.which() duplication that's happening here. In addition to not being sure if it's necessary, I'm worried about naming confusion.

replace_path = r'{}/[a-z0-9][a-z0-9+-]*/install'.format(
self._parts_dir)
assembled_env = re.sub(replace_path, '$SNAP', assembled_env)
re.escape(self._parts_dir))
Copy link
Contributor

Choose a reason for hiding this comment

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

This is used a few times. re.compile() might be a good idea.

'$LD_LIBRARY_PATH', file=f)
if cwd:
print('{}'.format(cwd), file=f)
print('exec {} {}'.format(executable, args), file=f)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just collect all the lines in a list and finally f.write('\n'.join(lines)) at the end?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I guess this boils down to personal preference, doesn't it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Indeed it does. Feel free to ignore.


args = ['pip', 'setuptools', 'wheel']

pip_command = [self._get_python_command(), '-m', 'pip']

# if python_command it is not from stage we don't have pip
Copy link
Contributor

Choose a reason for hiding this comment

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

s/if python_command it is/if python_command is/. Although from the comment I'm not sure how that relates to the setting of PYTHONHOME.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this can be clarified


env['PATH'] = '{}:{}'.format(
os.path.join(self.installdir, 'usr', 'bin'),
os.path.expandvars('$PATH'))
Copy link
Contributor

Choose a reason for hiding this comment

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

Huh, I didn't know about os.path.expandvars(), nice.

from snapcraft.internal import common


def which(command, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use the real shutil.which() with assemble_env()'s PATH? If we want to keep this, can we name the file something else? I'm afraid shutil will cause confusion later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is a common practice though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

also, we want the specific env to take precedence (PATH)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

assembled_env's PATH is a list with multiple entries of PATH

@adam-stokes
Copy link

adam-stokes commented Feb 1, 2017

I attempted to get my conjure-up snap working with this branch on trusty. This is the packaged snap contents of that:

http://paste.ubuntu.com/23907436/

I was able to install without an issue this time, however, here is the error i received:

/snap/conjure-up/x1/wrappers/conjure-up: 14: exec: /snap/conjure-up/x1/bin/conjure-up: not found

which goes inline with the contents of the snap.

On a plus though, my original issue with the systemd services not being installed have been resolved \o/

For reference here is my snapcraft im using https://github.com/conjure-up/conjure-up/blob/master/snap/snapcraft.yaml

Update

After adding the python part the build succeeded, however, I am getting another error when trying to start the systemd service:

ubuntu@darthbawlz:~$ systemctl status snap.conjure-up.bridge.service
Failed to issue method call: No such interface 'org.freedesktop.DBus.Properties' on object at path /org/freedesktop/systemd1/unit/snap_2econjure_2dup_2ebridge_2eservice

To fully enable classic confinment for python based snaps, there are
two big things that need to get done; no env var leaking and
use a python interpreter with the classic compilation flags.

LP: #1657504

Signed-off-by: Sergio Schvezov <sergio.schvezov@canonical.com>
@adam-stokes
Copy link

I've successfully tested this branch and was able to build https://github.com/conjure-up/conjure-up on Trusty with huge success.

else:
assembled_env = common.assemble_env()
assembled_env = assembled_env.replace(self._snap_dir, '$SNAP')
assembled_env = re.sub(replace_path, '$SNAP', assembled_env)
Copy link
Contributor

Choose a reason for hiding this comment

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

You probably want replace_path.sub('$SNAP', assembled_env) here, no?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ah, you should of been more specific; the current mechanism works though :-P


if shebang:
if shebang.startswith('/usr/bin/env '):
shebang = shell_utils.which(shebang.split()[1])
new_shebang = re.sub(replace_path, '$SNAP', shebang)
Copy link
Contributor

Choose a reason for hiding this comment

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

Right here too.

# If python_command it is not from stage we don't have pip, which means
# we are going to need to resort to the pip installed on the system
# that came from build-packages. This shouldn't be a problem as
# stage-packages and build-packages should match.
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 thank you. Though the typo is still there: s/python_command it is not/python_command is not/

Copy link
Contributor

@kyrofa kyrofa left a comment

Choose a reason for hiding this comment

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

Nice job on this, looks great!

@kyrofa kyrofa merged commit e782409 into canonical:master Feb 3, 2017
come-maiz pushed a commit that referenced this pull request Feb 28, 2017
To fully enable classic confinement for python based snaps, there are
two big things that need to get done; no env var leaking and
use a python interpreter with the classic compilation flags.

LP: #1657504

Signed-off-by: Sergio Schvezov <sergio.schvezov@canonical.com>
@sergiusens sergiusens deleted the bugfix/classic-python-plugin branch March 16, 2017 20:00
kalikiana pushed a commit to kalikiana/snapcraft that referenced this pull request Apr 6, 2017
To fully enable classic confinement for python based snaps, there are
two big things that need to get done; no env var leaking and
use a python interpreter with the classic compilation flags.

LP: #1657504

Signed-off-by: Sergio Schvezov <sergio.schvezov@canonical.com>
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

4 participants