Skip to content

Commit

Permalink
feature: add 'exec' returning a process and deprecates 'exec_command'
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabs committed Dec 24, 2018
1 parent 5c582b0 commit daebf75
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
62 changes: 62 additions & 0 deletions dcos_test_utils/dcos_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import tempfile
from typing import Optional

import deprecation
import requests

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -92,6 +93,67 @@ def clear_cli_dir():
if os.path.exists(path):
shutil.rmtree(path)

def exec(self, cmd: str, stdin=None, check=True) -> subprocess.CompletedProcess:
"""Execute CLI command and processes result.
This method expects that process won't block.
:param cmd: Program and arguments
:type cmd: str
:param stdin: File to use for stdin
:param check: Does it check for raised errors
:type stdin: typing.optional[File]
:returns: A tuple with stdout and stderr
:rtype: subprocess.CompletedProcess
:raises subprocess.CalledProcessError: When check=True if the returncode of \
cmd is not 0
exception description.
"""

log.info('CMD: {!r}'.format(cmd))

# Borrowed from dcos-e2e
# https://github.com/dcos/dcos-e2e/blob/8d4916780ade8caf41dae376fdf47f4253eb52c7/src/dcos_e2e/_common.py#L46-L59
def safe_decode(output_bytes: bytes) -> str:
"""
Decode a bytestring to Unicode with a safe fallback.
"""
try:
return output_bytes.decode(
encoding='utf-8',
errors='strict')
except UnicodeDecodeError:
return output_bytes.decode(
encoding='ascii',
errors='backslashreplace')

try:
process = subprocess.run(
cmd,
stdin=stdin,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=self.env,
check=check)
except subprocess.CalledProcessError as e:
stderr = safe_decode(e.stderr)
log.error('STDERR: {}'.format(stderr))

stdout = safe_decode(e.stdout)
log.error('STDOUT: {}'.format(stdout))

raise

stdout = safe_decode(process.stdout)
log.info('STDOUT: {}'.format(stdout))

stderr = safe_decode(process.stdout)
log.info('STDERR: {}'.format(stderr))

return process

@deprecation.deprecated(details="Deprecated in favor of the `exec` function. DCOS-44823")
def exec_command(self, cmd: str, stdin=None) -> tuple:
"""Execute CLI command and processes result.
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ pytest
requests
retrying
tox
deprecation

sphinx
41 changes: 40 additions & 1 deletion tests/test_dcos_cli.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import pytest
import subprocess

import deprecation
import pytest
from dcos_test_utils import dcos_cli


@deprecation.deprecated(details="Deprecated in favor of the `exec` function. DCOS-44823")
def test_exec_command(caplog):
cli = dcos_cli.DcosCli('')
stdout, stderr = cli.exec_command(
Expand All @@ -16,9 +18,46 @@ def test_exec_command(caplog):
assert any(rec.message.startswith('STDERR:') for rec in caplog.records)


@deprecation.deprecated(details="Deprecated in favor of the `exec` function. DCOS-44823")
def test_exec_command_fail(caplog):
cli = dcos_cli.DcosCli('')
with pytest.raises(subprocess.CalledProcessError):
cli.exec_command(['/bin/sh', '-c', 'does-not-exist'])
assert any(rec.message.startswith('CMD:') for rec in caplog.records)
assert any(rec.message.startswith('STDERR:') for rec in caplog.records)


def test_exec(caplog):
cli = dcos_cli.DcosCli('')
process = cli.exec(
['/bin/sh', '-c', 'echo "hello, world!"']
)
assert process.stdout == b'hello, world!\n'
assert process.stderr == b''
assert process.returncode == 0
assert any(rec.message.startswith('CMD:') for rec in caplog.records)
assert any(rec.message.startswith('STDOUT:') for rec in caplog.records)
assert any(rec.message.startswith('STDERR:') for rec in caplog.records)


def test_exec_fail(caplog):
cli = dcos_cli.DcosCli('')
with pytest.raises(subprocess.CalledProcessError):
cli.exec(['/bin/sh', '-c', 'does-not-exist'])
assert any(rec.message.startswith('CMD:') for rec in caplog.records)
assert any(rec.message.startswith('STDERR:') for rec in caplog.records)
assert any(rec.message.startswith('STDOUT:') for rec in caplog.records)


def test_exec_fail_without_check(caplog):
cli = dcos_cli.DcosCli('')
process = cli.exec(
['/bin/sh', '-c', 'does-not-exist'],
check=False
)
assert process.stdout == b''
assert b'does-not-exist' in process.stderr
assert process.returncode == 127
assert any(rec.message.startswith('CMD:') for rec in caplog.records)
assert any(rec.message.startswith('STDOUT:') for rec in caplog.records)
assert any(rec.message.startswith('STDERR:') for rec in caplog.records)

0 comments on commit daebf75

Please sign in to comment.