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

[pantsd] Set the remote environment for pantsd-runner and child processes. #5508

Merged
merged 7 commits into from Feb 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/python/pants/bin/daemon_pants_runner.py
Expand Up @@ -21,7 +21,7 @@
from pants.java.nailgun_io import NailgunStreamStdinReader, NailgunStreamWriter
from pants.java.nailgun_protocol import ChunkType, NailgunProtocol
from pants.pantsd.process_manager import ProcessManager
from pants.util.contextutil import HardSystemExit, stdio_as
from pants.util.contextutil import HardSystemExit, hermetic_environment_as, stdio_as
from pants.util.socket import teardown_socket


Expand Down Expand Up @@ -221,8 +221,8 @@ def post_fork_child(self):
# Setup a SIGINT signal handler.
self._setup_sigint_handler()

# Invoke a Pants run with stdio redirected.
with self._nailgunned_stdio(self._socket) as finalizer:
# Invoke a Pants run with stdio redirected and a proxied environment.
with self._nailgunned_stdio(self._socket) as finalizer, hermetic_environment_as(**self._env):
try:
# Setup the Exiter's finalizer.
self._exiter.set_finalizer(finalizer)
Expand Down
11 changes: 11 additions & 0 deletions src/python/pants/util/contextutil.py
Expand Up @@ -55,6 +55,17 @@ def setenv(key, val):
setenv(key, val)


@contextmanager
def hermetic_environment_as(**kwargs):
"""Set the environment to the supplied values from an empty state."""
old_environment, os.environ = os.environ, {}
try:
with environment_as(**kwargs):
yield
finally:
os.environ = old_environment


@contextmanager
def _stdio_stream_as(src_fd, dst_fd, dst_sys_attribute, mode):
"""Replace the given dst_fd and attribute on `sys` with an open handle to the given src_fd."""
Expand Down
42 changes: 41 additions & 1 deletion tests/python/pants_test/pantsd/test_pantsd_integration.py
Expand Up @@ -18,7 +18,7 @@

from pants.pantsd.process_manager import ProcessManager
from pants.util.collections import combined_dict
from pants.util.contextutil import temporary_dir
from pants.util.contextutil import environment_as, temporary_dir
from pants.util.dirutil import touch
from pants_test.pants_run_integration_test import PantsRunIntegrationTest
from pants_test.testutils.process_test_util import no_lingering_process_by_command
Expand Down Expand Up @@ -342,3 +342,43 @@ def test_pantsd_filesystem_invalidation(self):
checker.assert_running()

join()

def test_pantsd_client_env_var_is_inherited_by_pantsd_runner_children(self):
EXPECTED_VALUE = '333'
with self.pantsd_successful_run_context() as (pantsd_run, checker, workdir):
# First, launch the daemon without any local env vars set.
pantsd_run(['help'])
checker.await_pantsd()

# Then, set an env var on the secondary call.
with environment_as(TEST_ENV_VAR_FOR_PANTSD_INTEGRATION_TEST=EXPECTED_VALUE):
result = pantsd_run(
['-q',
'run',
'testprojects/src/python/print_env',
'--',
'TEST_ENV_VAR_FOR_PANTSD_INTEGRATION_TEST']
)
checker.assert_running()

self.assertEquals(EXPECTED_VALUE, ''.join(result.stdout_data).strip())

def test_pantsd_launch_env_var_is_not_inherited_by_pantsd_runner_children(self):
with self.pantsd_test_context() as (workdir, pantsd_config, checker):
with environment_as(NO_LEAKS='33'):
self.assert_success(
self.run_pants_with_workdir(
['help'],
workdir,
pantsd_config)
)
checker.await_pantsd()

self.assert_failure(
self.run_pants_with_workdir(
['-q', 'run', 'testprojects/src/python/print_env', '--', 'NO_LEAKS'],
workdir,
pantsd_config
)
)
checker.assert_running()
11 changes: 8 additions & 3 deletions tests/python/pants_test/util/test_contextutil.py
Expand Up @@ -18,9 +18,9 @@
import mock

from pants.util.contextutil import (HardSystemExit, InvalidZipPath, Timer, environment_as,
exception_logging, hard_exit_handler, maybe_profiled, open_zip,
pushd, signal_handler_as, stdio_as, temporary_dir,
temporary_file)
exception_logging, hard_exit_handler, hermetic_environment_as,
maybe_profiled, open_zip, pushd, signal_handler_as, stdio_as,
temporary_dir, temporary_file)
from pants.util.process_handler import subprocess


Expand Down Expand Up @@ -59,6 +59,11 @@ def test_environment_negation(self):
output.seek(0)
self.assertEquals('False\n', output.read())

def test_hermetic_environment(self):
self.assertIn('USER', os.environ)
with hermetic_environment_as(**{}):
self.assertNotIn('USER', os.environ)

def test_simple_pushd(self):
pre_cwd = os.getcwd()
with temporary_dir() as tempdir:
Expand Down