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']
Example #2
0
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']
Example #3
0
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()))
Example #5
0
 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'
Example #7
0
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
Example #9
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)
Example #17
0
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'