This commit:8971ccdb08Inadvertently undid changes originally introduced in this commit:f33a45ee94Unfortunately, the integration tests didn't catch this because all `task exec` integration tests were hidden behind an environment variable: @pytest.mark.skipif('DCOS_DEBUGGING_ENABLED' not in os.environ, reason="Requires Agent Debugging APIs") This commit reintroduces the changes that were inadvertently undone and enables the `task exec` integration tests by default so that something like this doesn't occur in the future.
197 lines
6.4 KiB
Python
197 lines
6.4 KiB
Python
import pytest
|
|
from mock import MagicMock, patch
|
|
|
|
from dcos import mesos
|
|
from dcos.errors import DCOSException
|
|
from dcoscli.log import log_files
|
|
from dcoscli.task.main import _dcos_log, _metrics, main
|
|
|
|
from .common import assert_mock
|
|
|
|
|
|
@patch('dcos.config.get_config')
|
|
def test_log_master_unavailable(config_mock):
|
|
config_mock.return_value = {'core.dcos_url': 'foo'}
|
|
|
|
""" Test master's state.json being unavailable """
|
|
client = mesos.DCOSClient()
|
|
client.get_master_state = _mock_exception()
|
|
|
|
with patch('dcos.mesos.DCOSClient', return_value=client):
|
|
args = ['task', 'log', '_']
|
|
assert_mock(main, args, returncode=1, stderr=(b"exception\n"))
|
|
|
|
|
|
def test_log_no_tasks():
|
|
""" Test slave's state.json being unavailable """
|
|
with patch('dcos.mesos.DCOSClient.get_master_state', return_value={}), \
|
|
patch('dcos.mesos.Master.tasks', return_value={}):
|
|
|
|
stderr = b"""No matching tasks. Exiting.\n"""
|
|
args = ['task', 'log', 'test-app-1']
|
|
assert_mock(main, args, returncode=1, stderr=stderr)
|
|
|
|
|
|
def test_task_exact_match():
|
|
"""Test a task gets returned if it is an exact match, even if
|
|
it is a substring of another task.
|
|
"""
|
|
with patch('dcos.mesos.Master.slaves',
|
|
return_value=[{"id": "foo"}, {"id": "foobar"}]):
|
|
master = mesos.Master(None)
|
|
assert master.slave("foo") == {"id": "foo"}
|
|
|
|
|
|
def test_log_file_unavailable():
|
|
""" Test a file's read.json being unavailable """
|
|
files = [mesos.MesosFile('bogus')]
|
|
files[0].read = _mock_exception('exception')
|
|
|
|
with pytest.raises(DCOSException) as e:
|
|
log_files(files, True, 10)
|
|
|
|
msg = "No files exist. Exiting."
|
|
assert e.exconly().split(':', 1)[1].strip() == msg
|
|
|
|
|
|
def _mock_exception(contents='exception'):
|
|
return MagicMock(side_effect=DCOSException(contents))
|
|
|
|
|
|
@patch('dcos.http.get')
|
|
@patch('dcos.config.get_config_val')
|
|
def test_dcos_log(mocked_get_config_val, mocked_http_get):
|
|
mocked_get_config_val.return_value = 'http://127.0.0.1'
|
|
|
|
m = MagicMock()
|
|
m.status_code = 200
|
|
mocked_http_get.return_value = m
|
|
|
|
executor_info = {
|
|
'tasks': [
|
|
{
|
|
'container': 'container1',
|
|
'state': 'TASK_RUNNING',
|
|
'statuses': [
|
|
{
|
|
'state': 'TASK_RUNNING',
|
|
'container_status': {
|
|
'container_id': {
|
|
'value': 'child-123',
|
|
'parent': {
|
|
'value': 'parent-456'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
],
|
|
'slave_id': 'slave-123',
|
|
'framework_id': 'framework-123',
|
|
'id': 'id-123'
|
|
}
|
|
]
|
|
}
|
|
|
|
task = MagicMock
|
|
task.executor = lambda: executor_info
|
|
_dcos_log(False, [task], 10, 'stdout', False)
|
|
mocked_http_get.assert_called_with(
|
|
'http://127.0.0.1/system/v1/agent/slave-123/logs/v1/range/framework/'
|
|
'framework-123/executor/id-123/container/parent-456.child-123'
|
|
'?skip_prev=10&filter=STREAM:STDOUT',
|
|
headers={'Accept': 'text/plain'})
|
|
|
|
|
|
@patch('dcoscli.log.follow_logs')
|
|
@patch('dcos.http.get')
|
|
@patch('dcos.config.get_config_val')
|
|
def test_dcos_log_stream(mocked_get_config_val, mocked_http_get,
|
|
mocked_follow_logs):
|
|
mocked_get_config_val.return_value = 'http://127.0.0.1'
|
|
|
|
m = MagicMock()
|
|
m.status_code = 200
|
|
mocked_http_get.return_value = m
|
|
|
|
executor_info = {
|
|
'tasks': [
|
|
{
|
|
'container': 'container1',
|
|
'state': 'TASK_RUNNING',
|
|
'statuses': [
|
|
{
|
|
'state': 'TASK_RUNNING',
|
|
'container_status': {
|
|
'container_id': {
|
|
'value': 'child-123',
|
|
}
|
|
}
|
|
}
|
|
],
|
|
'slave_id': 'slave-123',
|
|
'framework_id': 'framework-123',
|
|
'id': 'id-123'
|
|
}
|
|
]
|
|
}
|
|
|
|
task = MagicMock
|
|
task.executor = lambda: executor_info
|
|
_dcos_log(True, [task], 10, 'stderr', False)
|
|
mocked_follow_logs.assert_called_with(
|
|
'http://127.0.0.1/system/v1/agent/slave-123/logs/v1/'
|
|
'stream/framework/framework-123/executor/id-123/container/'
|
|
'child-123?skip_prev=10&filter=STREAM:STDERR')
|
|
|
|
|
|
@patch('dcos.http.get')
|
|
@patch('dcos.mesos.get_master')
|
|
@patch('dcos.config.get_config_val')
|
|
def test_dcos_task_metrics_agent_details(mocked_get_config_val,
|
|
mocked_get_master,
|
|
mocked_http_get):
|
|
mocked_get_config_val.return_value = 'http://127.0.0.1'
|
|
|
|
mock_http_response = MagicMock()
|
|
mock_http_response.status_code = 200
|
|
mocked_http_get.return_value = mock_http_response
|
|
|
|
mock_master = MagicMock()
|
|
mock_master.task = lambda _: {'slave_id': 'slave_id'}
|
|
mock_master.get_container_id = lambda _: {
|
|
'parent': {},
|
|
'value': 'container_id'
|
|
}
|
|
mocked_get_master.return_value = mock_master
|
|
|
|
_metrics(True, 'task_id', False)
|
|
|
|
# Metrics should query both endpoints
|
|
mocked_http_get.assert_any_call('http://127.0.0.1/system/v1/agent/'
|
|
'slave_id/metrics/v0/containers/'
|
|
'container_id/app')
|
|
mocked_http_get.assert_any_call('http://127.0.0.1/system/v1/agent/'
|
|
'slave_id/metrics/v0/containers/'
|
|
'container_id')
|
|
|
|
|
|
@patch('dcos.http.get')
|
|
@patch('dcos.mesos.get_master')
|
|
@patch('dcos.config.get_config_val')
|
|
def test_dcos_task_metrics_agent_missing_slave(mocked_get_config_val,
|
|
mocked_get_master,
|
|
mocked_http_get):
|
|
mocked_get_config_val.return_value = 'http://127.0.0.1'
|
|
|
|
mock_http_response = MagicMock()
|
|
mock_http_response.status_code = 200
|
|
mocked_http_get.return_value = mock_http_response
|
|
|
|
mock_master = MagicMock()
|
|
mock_master.task = lambda _: {}
|
|
mocked_get_master.return_value = mock_master
|
|
|
|
# Should a task not have a slave ID, expect an error
|
|
with pytest.raises(DCOSException):
|
|
_metrics(True, 'task_id', False)
|