# All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import logging import os import subprocess LOG = logging.getLogger(__name__) from subprocess import CalledProcessError # noqa def _multi_line_log(level, msg): for line in msg.splitlines(): LOG.log(level, line) def check_call(*popenargs, timeout=None, **kwargs): # A variation of subprocess.check_call that captures and then # logs the output of the command which makes it easier for tests # to capture it. kwargs['stdout'] = subprocess.PIPE kwargs['stderr'] = subprocess.STDOUT cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] if 'cwd' in kwargs: LOG.debug('cwd = {}'.format(kwargs['cwd'])) LOG.debug('$ {}'.format(' '.join(cmd))) # Copy full environment to pass in so we can include any of our own # environment variables with it. env = os.environ.copy() env_extras = kwargs.pop('env', None) if env_extras: env.update(env_extras) completed = subprocess.run(*popenargs, env=env, **kwargs) _multi_line_log(logging.DEBUG, completed.stdout.decode('utf-8')) if completed.returncode: raise subprocess.CalledProcessError(completed.returncode, cmd) return 0 def check_output(*popenargs, timeout=None, **kwargs): # A variation of subprocess.check_output that captures stderr and # logs it instead of letting it go to the console directly to make # it easier for tests to capture it. # NOTE(dhellmann): copied from subprocess.py vv if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it will be overridden.') if 'input' in kwargs and kwargs['input'] is None: # Explicitly passing input=None was previously equivalent to passing an # empty string. That is maintained here for backwards compatibility. kwargs['input'] = '' if kwargs.get('universal_newlines', False) else b'' # NOTE(dhellmann): end copied from subprocess.py ^^ cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] if 'cwd' in kwargs: LOG.debug('cwd = {}'.format(kwargs['cwd'])) LOG.debug('$ {}'.format(' '.join(cmd))) if 'stderr' not in kwargs: kwargs['stderr'] = subprocess.PIPE # Copy full environment to pass in so we can include any of our own # environment variables with it. env = os.environ.copy() env_extras = kwargs.pop('env', None) if env_extras: env.update(env_extras) completed = subprocess.run(*popenargs, stdout=subprocess.PIPE, timeout=timeout, check=True, env=env, **kwargs) if completed.stderr: _multi_line_log(logging.WARNING, completed.stderr.decode('utf-8')) return completed.stdout