60 lines
3.4 KiB
Python
60 lines
3.4 KiB
Python
import json
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
import unittest
|
|
import tempfile
|
|
from unittest.mock import patch
|
|
from console.native_container import command, cleanup
|
|
from console.native_io import read_secret_tables, SecretFilter
|
|
|
|
|
|
class NativeContainerTests(unittest.TestCase):
|
|
def test_registered_key_table_is_redacted_without_environment_injection(self):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
path = Path(temporary) / 'keys.txt'
|
|
path.write_text('# local fixture\noperator dummy-audio-key scope\n')
|
|
values = read_secret_tables([{'path': str(path), 'key_column': 1}])
|
|
self.assertEqual(values, ['dummy-audio-key'])
|
|
self.assertNotIn(b'dummy-audio-key', SecretFilter(values).clean(b'header=dummy-audio-key'))
|
|
|
|
def setUp(self):
|
|
self.identity = 'a' * 32
|
|
self.profile = {'docker': {'image': 'sha256:' + 'b' * 64, 'mounts': [{'source': '/original/tests', 'target': '/t'}]},
|
|
'interpreter': '/opt/omni/bin/python'}
|
|
|
|
def test_fixed_image_readonly_sources_and_owned_output_without_gpu(self):
|
|
args = command(self.profile, Path('/original/tests/test_api.py'), ['x'], '/runs/' + self.identity, self.identity)
|
|
self.assertIn('xas.native-run=' + self.identity, args)
|
|
self.assertIn('type=bind,src=/original/tests,dst=/t,readonly', args)
|
|
self.assertIn('type=bind,src=/runs/' + self.identity + '/work,dst=/out', args)
|
|
self.assertEqual(args[-4:], [self.profile['docker']['image'], '-u', '/t/test_api.py', 'x'])
|
|
self.assertNotIn('--gpus', args)
|
|
self.assertIn('runc', args)
|
|
|
|
def test_cleanup_rejects_foreign_container(self):
|
|
inspected = SimpleNamespace(returncode=0, stdout=json.dumps([{'Name': '/adamwen-native-run-' + self.identity,
|
|
'Config': {'Labels': {'xas.native-run': 'other'}}}]), stderr='')
|
|
with patch('console.native_container.subprocess.run', return_value=inspected) as call:
|
|
with self.assertRaises(ValueError): cleanup(self.identity)
|
|
self.assertEqual(call.call_count, 1)
|
|
|
|
def test_daemon_error_is_not_treated_as_container_missing(self):
|
|
error = SimpleNamespace(returncode=1, stdout='', stderr='Cannot connect to Docker daemon')
|
|
with patch('console.native_container.subprocess.run', return_value=error):
|
|
with self.assertRaises(OSError): cleanup(self.identity)
|
|
|
|
def test_missing_owned_container_is_already_clean(self):
|
|
missing = SimpleNamespace(returncode=1, stdout='', stderr='error: no such object: adamwen-native-run-' + self.identity)
|
|
with patch('console.native_container.subprocess.run', return_value=missing) as call:
|
|
cleanup(self.identity)
|
|
self.assertEqual(call.call_count, 1)
|
|
|
|
def test_auto_removed_container_race_is_not_an_uncertain_cleanup(self):
|
|
container_id = 'c' * 64
|
|
inspected = SimpleNamespace(returncode=0, stdout=json.dumps([{'Id':container_id,
|
|
'Name':'/adamwen-native-run-' + self.identity,'Config':{'Labels':{'xas.native-run':self.identity}}}]),stderr='')
|
|
gone = SimpleNamespace(returncode=1,stdout='',stderr='Error: No such container: ' + container_id)
|
|
with patch('console.native_container.subprocess.run',side_effect=[inspected,gone,gone]) as call:
|
|
cleanup(self.identity)
|
|
self.assertEqual(call.call_args_list[1].args[0][-1],container_id)
|