mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-30 00:27:11 +09:00
125 lines
4.4 KiB
Python
125 lines
4.4 KiB
Python
"""Runtime-aware application logs keep single-container and compose support."""
|
|
import os
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from factories import headers_for, make_application, make_server, make_user
|
|
|
|
|
|
@pytest.fixture
|
|
def owner(app, db_session):
|
|
return make_user(db_session, role='admin', username='observability-owner')
|
|
|
|
|
|
def test_logs_prefer_a_live_recorded_container(client, db_session, owner, tmp_path):
|
|
"""A repository compose file does not override the deployed runtime."""
|
|
(tmp_path / 'docker-compose.yaml').write_text(
|
|
'services:\n db:\n image: postgres\n', encoding='utf-8')
|
|
application = make_application(
|
|
db_session,
|
|
name='standalone-api',
|
|
root_path=str(tmp_path),
|
|
compose_file=None,
|
|
container_id='runtime-container-id',
|
|
user_id=owner.id,
|
|
)
|
|
|
|
with patch('app.api.apps.DockerService.get_container',
|
|
return_value={'Id': 'runtime-container-id'}), \
|
|
patch('app.api.apps.DockerService.get_container_logs',
|
|
return_value={'success': True, 'logs': 'ready'}) as direct, \
|
|
patch('app.api.apps.LogService.get_docker_app_logs') as compose:
|
|
response = client.get(
|
|
f'/api/v1/apps/{application.id}/logs?lines=250',
|
|
headers=headers_for(owner),
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert response.get_json()['logs'] == 'ready'
|
|
direct.assert_called_once_with(
|
|
'runtime-container-id', tail=250, timestamps=False)
|
|
compose.assert_not_called()
|
|
|
|
|
|
def test_logs_fall_back_to_compose_for_legacy_records(
|
|
client, db_session, owner, tmp_path):
|
|
application = make_application(
|
|
db_session,
|
|
name='legacy-compose',
|
|
root_path=str(tmp_path),
|
|
compose_file='compose.yaml',
|
|
container_id=None,
|
|
user_id=owner.id,
|
|
)
|
|
|
|
with patch('app.api.apps.LogService.get_docker_app_logs',
|
|
return_value={'success': True, 'logs': 'compose-ready'}) as compose:
|
|
response = client.get(
|
|
f'/api/v1/apps/{application.id}/logs?lines=75',
|
|
headers=headers_for(owner),
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert response.get_json()['logs'] == 'compose-ready'
|
|
compose.assert_called_once_with(
|
|
'legacy-compose', str(tmp_path), 75, compose_file='compose.yaml')
|
|
|
|
|
|
def test_a_stale_recorded_container_keeps_the_compose_fallback(
|
|
client, db_session, owner, tmp_path):
|
|
application = make_application(
|
|
db_session,
|
|
name='recreated-compose',
|
|
root_path=str(tmp_path),
|
|
compose_file='compose.yaml',
|
|
container_id='removed-container-id',
|
|
user_id=owner.id,
|
|
)
|
|
|
|
with patch('app.api.apps.DockerService.get_container', return_value=None), \
|
|
patch('app.api.apps.DockerService.get_container_logs') as direct, \
|
|
patch('app.api.apps.LogService.get_docker_app_logs',
|
|
return_value={'success': True, 'logs': 'fallback-ready'}) as compose:
|
|
response = client.get(
|
|
f'/api/v1/apps/{application.id}/logs',
|
|
headers=headers_for(owner),
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert response.get_json()['logs'] == 'fallback-ready'
|
|
direct.assert_not_called()
|
|
compose.assert_called_once()
|
|
|
|
|
|
def test_remote_logs_never_resolve_a_container_on_the_panel(
|
|
client, db_session, owner):
|
|
server = make_server(db_session, name='remote-runtime')
|
|
application = make_application(
|
|
db_session,
|
|
name='remote-api',
|
|
root_path='/srv/remote-api',
|
|
compose_file='compose.yaml',
|
|
container_id='runtime-container-id',
|
|
server_id=server.id,
|
|
user_id=owner.id,
|
|
)
|
|
|
|
with patch('app.api.apps.DockerService.get_container') as inspect, \
|
|
patch('app.api.apps.DockerService.get_container_logs') as direct, \
|
|
patch('app.api.apps.RemoteDockerService.compose_logs',
|
|
return_value={'success': True,
|
|
'data': {'logs': 'remote-ready'}}) as remote:
|
|
response = client.get(
|
|
f'/api/v1/apps/{application.id}/logs?lines=75',
|
|
headers=headers_for(owner),
|
|
)
|
|
|
|
assert response.status_code == 200
|
|
assert response.get_json()['logs'] == 'remote-ready'
|
|
inspect.assert_not_called()
|
|
direct.assert_not_called()
|
|
remote.assert_called_once_with(
|
|
server.id, os.path.join('/srv/remote-api', 'compose.yaml'), tail=75,
|
|
user_id=str(owner.id))
|