2019-11-12 16:09:47 +00:00
|
|
|
import os.path
|
2019-11-13 19:50:33 +00:00
|
|
|
|
2019-11-12 16:09:47 +00:00
|
|
|
from datetime import datetime, timedelta
|
|
|
|
|
|
|
|
from app import storage
|
|
|
|
|
|
|
|
from data import model
|
|
|
|
from data.database import LogEntry, LogEntry2, LogEntry3
|
|
|
|
from data.logs_model.elastic_logs import INDEX_NAME_PREFIX, INDEX_DATE_FORMAT
|
|
|
|
from data.logs_model.datatypes import AggregatedLogCount, LogEntriesPage, Log
|
|
|
|
from data.logs_model.document_logs_model import DocumentLogsModel
|
|
|
|
from data.logs_model.test.fake_elasticsearch import FAKE_ES_HOST, fake_elasticsearch
|
|
|
|
from data.logs_model.table_logs_model import TableLogsModel
|
|
|
|
from data.logs_model.combined_model import CombinedLogsModel
|
|
|
|
from data.logs_model.inmemory_model import InMemoryModel
|
|
|
|
|
|
|
|
from data.logs_model import LogsModelProxy
|
|
|
|
|
|
|
|
from util.timedeltastring import convert_to_timedelta
|
|
|
|
from workers.logrotateworker import LogRotateWorker, SAVE_PATH, SAVE_LOCATION
|
|
|
|
|
|
|
|
from test.fixtures import *
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def clear_db_logs(initialized_db):
|
|
|
|
LogEntry.delete().execute()
|
|
|
|
LogEntry2.delete().execute()
|
|
|
|
LogEntry3.delete().execute()
|
|
|
|
|
|
|
|
|
|
|
|
def combined_model():
|
|
|
|
return CombinedLogsModel(TableLogsModel(), InMemoryModel())
|
|
|
|
|
|
|
|
|
|
|
|
def es_model():
|
|
|
|
return DocumentLogsModel(producer='elasticsearch', elasticsearch_config={
|
|
|
|
'host': FAKE_ES_HOST,
|
|
|
|
'port': 12345,
|
|
|
|
})
|
|
|
|
|
|
|
|
@pytest.fixture()
|
|
|
|
def fake_es():
|
|
|
|
with fake_elasticsearch():
|
|
|
|
yield
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(params=[TableLogsModel, es_model, InMemoryModel, combined_model])
|
|
|
|
def logs_model(request, clear_db_logs, fake_es):
|
|
|
|
model = request.param()
|
|
|
|
with patch('data.logs_model.logs_model', model):
|
|
|
|
with patch('workers.logrotateworker.logs_model', model):
|
|
|
|
yield model
|
|
|
|
|
|
|
|
|
|
|
|
def _lookup_logs(logs_model, start_time, end_time, **kwargs):
|
|
|
|
logs_found = []
|
|
|
|
page_token = None
|
|
|
|
while True:
|
|
|
|
found = logs_model.lookup_logs(start_time, end_time, page_token=page_token, **kwargs)
|
|
|
|
logs_found.extend(found.logs)
|
|
|
|
page_token = found.next_page_token
|
|
|
|
if not found.logs or not page_token:
|
|
|
|
break
|
|
|
|
|
|
|
|
assert len(logs_found) == len(set(logs_found))
|
|
|
|
return logs_found
|
|
|
|
|
|
|
|
|
|
|
|
def test_logrotateworker(logs_model):
|
|
|
|
worker = LogRotateWorker()
|
|
|
|
days = 90
|
|
|
|
start_timestamp = datetime(2019, 1, 1)
|
|
|
|
|
|
|
|
# Make sure there are no existing logs
|
|
|
|
found = _lookup_logs(logs_model, start_timestamp - timedelta(days=1000), start_timestamp + timedelta(days=1000))
|
|
|
|
assert not found
|
|
|
|
|
|
|
|
# Create some logs
|
|
|
|
for day in range(0, days):
|
|
|
|
logs_model.log_action('push_repo', namespace_name='devtable', repository_name='simple',
|
|
|
|
ip='1.2.3.4', timestamp=start_timestamp-timedelta(days=day))
|
|
|
|
|
|
|
|
# Ensure there are logs.
|
|
|
|
logs = _lookup_logs(logs_model,
|
|
|
|
start_timestamp - timedelta(days=1000),
|
|
|
|
start_timestamp + timedelta(days=1000))
|
|
|
|
|
|
|
|
assert len(logs) == days
|
|
|
|
|
|
|
|
# Archive all the logs.
|
|
|
|
assert worker._perform_archiving(start_timestamp + timedelta(days=1))
|
|
|
|
|
|
|
|
# Ensure all the logs were archived.
|
|
|
|
found = _lookup_logs(logs_model, start_timestamp - timedelta(days=1000), start_timestamp + timedelta(days=1000))
|
|
|
|
assert not found
|
|
|
|
|
|
|
|
|
|
|
|
def test_logrotateworker_with_cutoff(logs_model):
|
|
|
|
days = 60
|
|
|
|
start_timestamp = datetime(2019, 1, 1)
|
|
|
|
|
|
|
|
# Make sure there are no existing logs
|
|
|
|
found = _lookup_logs(logs_model, start_timestamp - timedelta(days=365), start_timestamp + timedelta(days=365))
|
|
|
|
assert not found
|
|
|
|
|
|
|
|
# Create a new set of logs/indices.
|
|
|
|
for day in range(0, days):
|
|
|
|
logs_model.log_action('push_repo', namespace_name='devtable', repository_name='simple',
|
|
|
|
ip='1.2.3.4', timestamp=start_timestamp+timedelta(days=day))
|
|
|
|
|
|
|
|
# Get all logs
|
|
|
|
logs = _lookup_logs(logs_model,
|
|
|
|
start_timestamp - timedelta(days=days-1),
|
|
|
|
start_timestamp + timedelta(days=days+1))
|
|
|
|
|
|
|
|
assert len(logs) == days
|
|
|
|
|
|
|
|
# Set the cutoff datetime to be the midpoint of the logs
|
|
|
|
midpoint = logs[0:len(logs)/2]
|
|
|
|
assert midpoint
|
|
|
|
assert len(midpoint) < len(logs)
|
|
|
|
|
|
|
|
worker = LogRotateWorker()
|
|
|
|
cutoff_date = midpoint[-1].datetime
|
|
|
|
|
|
|
|
# Archive the indices at or older than the cutoff date
|
|
|
|
archived_files = worker._perform_archiving(cutoff_date)
|
|
|
|
|
|
|
|
# Ensure the eariler logs were archived
|
|
|
|
found = _lookup_logs(logs_model, start_timestamp, cutoff_date-timedelta(seconds=1))
|
|
|
|
assert not found
|
|
|
|
|
|
|
|
# Check that the files were written to storage
|
|
|
|
for archived_file in archived_files:
|
|
|
|
assert storage.exists([SAVE_LOCATION], os.path.join(SAVE_PATH, archived_file))
|
|
|
|
|
|
|
|
# If current model uses ES, check that the indices were also deleted
|
|
|
|
if isinstance(logs_model, DocumentLogsModel):
|
|
|
|
assert len(logs_model.list_indices()) == days - (len(logs) / 2)
|
|
|
|
for index in logs_model.list_indices():
|
|
|
|
dt = datetime.strptime(index[len(INDEX_NAME_PREFIX):], INDEX_DATE_FORMAT)
|
|
|
|
assert dt >= cutoff_date
|