Merge lp:~cjwatson/launchpad/utilities-run-as into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18500
Proposed branch: lp:~cjwatson/launchpad/utilities-run-as
Merge into: lp:launchpad
Diff against target: 40 lines (+36/-0)
1 file modified
utilities/run-as (+36/-0)
To merge this branch: bzr merge lp:~cjwatson/launchpad/utilities-run-as
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+332290@code.launchpad.net

Commit message

Add a utility to make it easier to run Launchpad code inside "lxc exec".

Description of the change

I've had this lying around as ~/bin/lp-su for a while, but it seems more generally useful. Running the test suite in a running container becomes:

  lxc exec "$container_name" -- $PWD/utilities/run-as $USER bin/with-xvfb bin/test -vvc

... which is still a hefty pile of adverbs, but isn't too bad.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'utilities/run-as'
2--- utilities/run-as 1970-01-01 00:00:00 +0000
3+++ utilities/run-as 2017-10-16 11:23:24 +0000
4@@ -0,0 +1,36 @@
5+#! /usr/bin/python
6+#
7+# Copyright 2017 Canonical Ltd. This software is licensed under the
8+# GNU Affero General Public License version 3 (see the file LICENSE).
9+
10+"""Run a command as another user and with the proper environment.
11+
12+This can only be run as root, and makes it easier to run Launchpad code
13+inside "lxc exec". (sudo in xenial breaks without a tty, so cannot be used
14+here.)
15+"""
16+
17+from __future__ import absolute_import, print_function, unicode_literals
18+
19+import os
20+import pwd
21+import resource
22+import sys
23+
24+
25+user = sys.argv[1]
26+pw = pwd.getpwnam(user)
27+os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid)
28+os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid)
29+os.environ["HOME"] = pw.pw_dir
30+os.environ["SHELL"] = pw.pw_shell
31+os.environ["USER"] = user
32+os.environ["LOGNAME"] = user
33+os.chdir(os.path.dirname(os.path.dirname(__file__)))
34+# The current default is 1048576, which is rather over the top and causes
35+# GPGME-based tests to be extremely slow. See:
36+# https://lists.gnupg.org/pipermail/gnupg-devel/2017-September/033086.html
37+soft_nofile, hard_nofile = resource.getrlimit(resource.RLIMIT_NOFILE)
38+if hard_nofile > 4096:
39+ resource.setrlimit(resource.RLIMIT_NOFILE, (min(soft_nofile, 4096), 4096))
40+os.execvp(sys.argv[2], sys.argv[2:])