def test_linebuffer_callback(): buffered = [] def callback(fd, data): buffered.append(data) _call(('bash', '-c', 'echo 1; echo 2; echo 3'), callback_linebuffered=callback) assert buffered == ['1', '2', '3']
def test_linebuffer_callback(): buffered = [] def callback(fd, data): # noqa; pylint: disable=unused-argument buffered.append(data) _call(('bash', '-c', 'echo 1; echo 2; echo 3'), callback_linebuffered=callback) assert buffered == ['1', '2', '3']
def run(args, split=False): """ Run a command and return its result as a dict. The execution of the program and it's results are captured by the audit. :param args: Command to execute :type args: list or tuple :param split: Split the output on newlines :type split: bool :return: {'stdout' : stdout, 'stderr': stderr, 'signal': signal, 'exit_code': exit_code, 'pid': pid} :rtype: dict """ _id = str(uuid.uuid4()) result = None try: create_audit_entry('process-start', {'id': _id, 'parameters': args}) result = _call(args, callback_raw=_logging_handler) if result['exit_code'] != 0: raise CalledProcessError( message="A Leapp Command Error occurred. ", command=args, result=result) else: if split: result.update({'stdout': result['stdout'].splitlines()}) finally: create_audit_entry('process-end', _id) create_audit_entry('process-result', { 'id': _id, 'parameters': args, 'result': result }) return result
def test_utf8_panagrams(): panagrams_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'data', 'call_data', 'panagrams') with open(panagrams_path, 'rb') as f: p_raw = f.read() panagrams = p_raw.decode('utf-8') primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 ] for prime in primes: _lines, _raw = ArrayTracer(), ArrayTracer() r = _call(( 'cat', panagrams_path, ), read_buffer_size=prime, callback_linebuffered=_lines, callback_raw=_raw) assert r['stdout'] == panagrams assert panagrams.splitlines() == _lines.value assert p_raw == bytes( functools.reduce(lambda x, xs: x + xs, _raw.value, bytes()))
def _get_packages(self): cmd = ['/bin/bash', '-c', 'rpm -qa --queryformat="%{nevra} %{SIGPGP:pgpsig}\n" | grep -Ee "leapp|snactor"'] res = _call(cmd, lambda x, y: None, lambda x, y: None) if res.get('exit_code', None) == 0: if res.get('stdout', None): return [{'nevra': t[0], 'signature': t[1]} for t in [line.strip().split(' ', 1) for line in res['stdout'].split('\n') if line.strip()]] return []
def test_stdin_fd(): r, w = os.pipe() # The string we write here should not exceed `/proc/sys/fs/pipe-max-size` # which represents the size of the kernel buffer backing the pipe os.write(w, b'LOREM IPSUM') os.close(w) ret = _call(('bash', '-c', 'read MSG; echo "<$MSG>"'), stdin=r) os.close(r) assert ret['stdout'] == '<LOREM IPSUM>\n'
def run(args, split=False, callback_raw=_console_logging_handler, callback_linebuffered=_logfile_logging_handler, env=None, checked=True): """ Run a command and return its result as a dict. The execution of the program and it's results are captured by the audit. :param args: Command to execute :type args: list or tuple :param split: Split the output on newlines :type split: bool :param callback_raw: Optional custom callback executed on raw data to print in console :type callback_raw: (fd: int, buffer: bytes) -> None :param env: Environment variables to use for execution of the command :type env: dict :param checked: Raise an exception on a non-zero exit code, default True :type checked: bool :return: {'stdout' : stdout, 'stderr': stderr, 'signal': signal, 'exit_code': exit_code, 'pid': pid} :rtype: dict """ api.current_logger().debug('External command is started: [%s]', ' '.join(args)) _id = str(uuid.uuid4()) result = None try: create_audit_entry('process-start', { 'id': _id, 'parameters': args, 'env': env }) result = _call(args, callback_raw=callback_raw, callback_linebuffered=callback_linebuffered, env=env) if checked and result['exit_code'] != 0: raise CalledProcessError( message="A Leapp Command Error occurred. ", command=args, result=result) if split: result.update({'stdout': result['stdout'].splitlines()}) finally: create_audit_entry('process-end', _id) create_audit_entry('process-result', { 'id': _id, 'parameters': args, 'result': result, 'env': env }) api.current_logger().debug('External command is finished: [%s]', ' '.join(args)) return result
def test_output_1(): ret = _call(('false', )) assert isinstance(ret['exit_code'], int) assert ret['exit_code'] == 1 assert isinstance(ret['pid'], int) assert ret['pid'] > 0 assert ret['stdout'] == '' assert ret['stderr'] == '' assert isinstance(ret['signal'], int) assert ret['signal'] == 0
def test_env_preservation(): os.environ['TEST'] = 'FAILURE' ret = _call(('bash', '-c', 'echo $TEST'), env={ 'TEST': 'SUCCESS', 'TEST2': 'HELLO_WORLD' }) assert isinstance(ret['exit_code'], int) assert ret['exit_code'] == 0 assert 'TEST2' not in os.environ assert os.environ['TEST'] == 'FAILURE' assert ret['stdout'] == 'SUCCESS\n'
def test_output_2(): ret = _call(( 'bash', '-c', 'echo STDOUT; (exec >&2 ; echo STDERR); exit 42', )) assert isinstance(ret['exit_code'], int) assert ret['exit_code'] == 42 assert isinstance(ret['pid'], int) assert ret['pid'] > 0 assert ret['stdout'] == 'STDOUT\n' assert ret['stderr'] == 'STDERR\n' assert isinstance(ret['signal'], int) assert ret['signal'] == 0
def test_callability_check(p): with pytest.raises(TypeError): _call(('true', ), callback_raw='nope')
def test_env_injection(): ret = _call(('bash', '-c', 'echo $TEST'), env={'TEST': 'SUCCESS'}) assert isinstance(ret['exit_code'], int) assert ret['exit_code'] == 0 assert ret['stdout'] == 'SUCCESS\n'
def test_stdin_check(p): with pytest.raises(TypeError): _call(('true', ), stdin=p)
def test_callability_check(p): with pytest.raises(TypeError): _call(('true', ), callback_linebuffered=p)
def test_invalid_command(): with pytest.raises(TypeError): _call('i should be a list or tuple really')
def test_buffer_size(p): with pytest.raises(ValueError): _call(('true', ), read_buffer_size=p)
def run(args, split=False, callback_raw=_console_logging_handler, callback_linebuffered=_logfile_logging_handler, env=None, checked=True, stdin=None): """ Run a command and return its result as a dict. The execution of the program and it's results are captured by the audit. :param args: Command to execute :type args: list or tuple :param split: Split the output on newlines :type split: bool :param callback_raw: Optional custom callback executed on raw data to print in console :type callback_raw: (fd: int, buffer: bytes) -> None :param env: Environment variables to use for execution of the command :type env: dict :param checked: Raise an exception on a non-zero exit code, default True :type checked: bool :param stdin: String or a file descriptor that will be written to stdin of the child process :type stdin: int, str :return: {'stdout' : stdout, 'stderr': stderr, 'signal': signal, 'exit_code': exit_code, 'pid': pid} :rtype: dict """ if not args: message = 'Command to call is missing.' api.current_logger().error(message) raise ValueError(message) api.current_logger().debug('External command has started: {0}'.format( str(args))) _id = str(uuid.uuid4()) result = None try: create_audit_entry('process-start', { 'id': _id, 'parameters': args, 'env': env }) result = _call(args, callback_raw=callback_raw, callback_linebuffered=callback_linebuffered, stdin=stdin, env=env) if checked and result['exit_code'] != 0: message = 'Command {0} failed with exit code {1}.'.format( str(args), result.get('exit_code')) api.current_logger().debug(message) raise CalledProcessError(message=message, command=args, result=result) if split: result.update({'stdout': result['stdout'].splitlines()}) finally: create_audit_entry('process-result', { 'id': _id, 'parameters': args, 'result': result, 'env': env }) api.current_logger().debug('External command has finished: {0}'.format( str(args))) return result
def test_polltime(p): with pytest.raises(ValueError): _call(('true', ), poll_timeout=p)
def test_stdin_string(): ret = _call(('bash', '-c', 'read MSG; echo "<$MSG>"'), stdin='LOREM IPSUM') assert ret['stdout'] == '<LOREM IPSUM>\n'