mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-01 10:22:08 +00:00
87 lines
5.1 KiB
Python
87 lines
5.1 KiB
Python
"""Internal service metadata is inferred from OCI, not app-specific recipes."""
|
|
import json
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import unittest
|
|
from types import SimpleNamespace
|
|
from unittest.mock import patch
|
|
|
|
ROOT=Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0,str(ROOT/'src'))
|
|
sys.path.insert(0,str(ROOT/'remote'))
|
|
from proxmenux_oci.custom import enrich_image_defaults
|
|
import install_generic_stack as generic
|
|
|
|
|
|
class ImageDefaults(unittest.TestCase):
|
|
def test_internal_expose_and_health_from_oci_are_preserved_without_publishing_ports(self):
|
|
doc={'services':{'helper':{'image':'example.org/team/helper:3','healthcheck':{'disable':False,'retries':5}}}}
|
|
config={'config':{'ExposedPorts':{'7000/tcp':{},'7001/udp':{}},'Healthcheck':{
|
|
'Test':['CMD','/usr/bin/check-ready'],'Interval':3000000000,'Timeout':1000000000}}}
|
|
process=SimpleNamespace(returncode=0,stdout=json.dumps(config))
|
|
with patch('proxmenux_oci.custom.subprocess.run',return_value=process):
|
|
result=enrich_image_defaults(None,doc)['services']['helper']
|
|
self.assertEqual(result['expose'],['7000/tcp'])
|
|
self.assertNotIn('ports',result)
|
|
self.assertEqual(result['healthcheck']['test'],['CMD','/usr/bin/check-ready'])
|
|
self.assertEqual(result['healthcheck']['retries'],5)
|
|
self.assertEqual(result['healthcheck']['interval'],'3000000000ns')
|
|
self.assertNotIn('expose',doc['services']['helper'])
|
|
|
|
def test_null_image_health_does_not_crash_and_no_port_is_invented(self):
|
|
doc={'services':{'helper':{'image':'example.org/team/helper:3','healthcheck':{'disable':False}}}}
|
|
with patch('proxmenux_oci.custom.subprocess.run',return_value=SimpleNamespace(returncode=0,stdout='{"config":{"Healthcheck":null}}')):
|
|
result=enrich_image_defaults(None,doc)['services']['helper']
|
|
self.assertNotIn('healthcheck',result)
|
|
self.assertNotIn('expose',result)
|
|
|
|
def test_explicit_disabled_healthcheck_is_not_reenabled(self):
|
|
doc={'services':{'web':{'image':'example.org/web:1','ports':['8080:8080'],'healthcheck':{'disable':True}}}}
|
|
with patch('proxmenux_oci.custom.subprocess.run') as inspect:
|
|
self.assertEqual(enrich_image_defaults(None,doc),doc)
|
|
inspect.assert_not_called()
|
|
|
|
def test_worker_entrypoint_or_command_does_not_inherit_a_false_web_listener(self):
|
|
for override in [{'entrypoint':'/cron.sh'}, {'command':['worker','run']}, {'command':[]}]:
|
|
with self.subTest(override=override):
|
|
doc={'services':{'worker':{'image':'example.org/web-and-worker:1',**override}}}
|
|
config={'config':{'ExposedPorts':{'80/tcp':{}},'Healthcheck':None}}
|
|
with patch('proxmenux_oci.custom.subprocess.run',return_value=SimpleNamespace(returncode=0,stdout=json.dumps(config))):
|
|
result=enrich_image_defaults(None,doc)['services']['worker']
|
|
self.assertNotIn('expose',result)
|
|
|
|
def test_option_command_uses_actual_image_entrypoint_metadata(self):
|
|
doc={'services':{'db':{'image':'mariadb:11','command':['--transaction-isolation=READ-COMMITTED']}}}
|
|
config={'config':{'Entrypoint':['docker-entrypoint.sh'],'Cmd':['mariadbd']}}
|
|
entrypoints={}
|
|
with patch('proxmenux_oci.custom.subprocess.run',return_value=SimpleNamespace(returncode=0,stdout=json.dumps(config))):
|
|
result=enrich_image_defaults(None,doc,image_entrypoints=entrypoints)
|
|
self.assertEqual(entrypoints,{'mariadb:11':['docker-entrypoint.sh']})
|
|
self.assertEqual(result,doc)
|
|
|
|
def test_enforcing_selinux_stops_before_install_when_labels_need_translation(self):
|
|
import tempfile
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
path=Path(directory)/'enforce'; path.write_text('1')
|
|
with self.assertRaisesRegex(RuntimeError,'SELinux'):
|
|
generic.check_selinux_labels({'proxmox':{'custom_compose_selinux_labels':True}},path)
|
|
path.write_text('0')
|
|
generic.check_selinux_labels({'proxmox':{'custom_compose_selinux_labels':True}},path)
|
|
path.write_text('1')
|
|
generic.check_selinux_labels({'proxmox':{}},path)
|
|
|
|
def test_main_http_success_does_not_override_failed_declared_exec_health(self):
|
|
service={'vmid':4800,'name':'app','healthcheck':{'type':'exec','argv':['check-ready'],'timeout_seconds':30}}
|
|
opener=SimpleNamespace(open=lambda *args,**kwargs: __import__('contextlib').nullcontext(SimpleNamespace(status=200)))
|
|
with patch.object(generic,'run',return_value='status: running'), \
|
|
patch.object(generic.urllib.request,'build_opener',return_value=opener), \
|
|
patch.object(generic.subprocess,'run',side_effect=[SimpleNamespace(returncode=1),SimpleNamespace(returncode=0)]) as execute, \
|
|
patch.object(generic.time,'sleep'):
|
|
generic.wait_web(service,'http://192.0.2.1:8080/')
|
|
self.assertEqual(execute.call_count,2)
|
|
self.assertEqual(execute.call_args.args[0],['pct','exec','4800','--','check-ready'])
|
|
|
|
|
|
if __name__=='__main__':unittest.main()
|