mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-02 19:02:31 +00:00
65 lines
3.4 KiB
Python
65 lines
3.4 KiB
Python
"""Internal TCP readiness survives initial install, native lifecycle and restore."""
|
|||
|
|
import copy
|
||
|
|
from pathlib import Path
|
||
|
|
import socket
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
import unittest
|
||
|
|
from unittest.mock import patch
|
||
|
|
|
||
|
|
ROOT = Path(__file__).resolve().parents[1]
|
||
|
|
sys.path.insert(0, str(ROOT/'remote'))
|
||
|
|
import install_generic_stack as installer
|
||
|
|
import oci_stack_native as native
|
||
|
|
import oci_restore_recovery as recovery
|
||
|
|
|
||
|
|
|
||
|
|
class TCPReadinessTests(unittest.TestCase):
|
||
|
|
def test_initial_runtime_probe_uses_allocated_private_address(self):
|
||
|
|
service={'ip':'10.77.20.31','healthcheck':{'type':'tcp','port':9998,'timeout_seconds':120}}
|
||
|
|
installer.assign_health_address(service)
|
||
|
|
self.assertEqual(service['healthcheck']['host'],'10.77.20.31')
|
||
|
|
self.assertNotIn('url',service['healthcheck'])
|
||
|
|
self.assertNotIn('frontend',service)
|
||
|
|
|
||
|
|
def test_native_health_probes_real_socket_without_http(self):
|
||
|
|
with socket.socket() as server:
|
||
|
|
server.bind(('127.0.0.1',0));server.listen()
|
||
|
|
port=server.getsockname()[1]
|
||
|
|
member={'vmid':4800,'deployment':{},'stack':{'deployment':{'services':[
|
||
|
|
{'vmid':4800,'name':'helper','healthcheck':{'type':'tcp','host':'127.0.0.1','port':port,'timeout_seconds':5}}]}}}
|
||
|
|
adapter=native.NativeAdapter(Path('/registry'),Path('/journal'),{'members':[member],'primary_vmid':4800})
|
||
|
|
with patch.object(adapter,'is_running',return_value=True), \
|
||
|
|
patch.object(native.member_tx.gpu_devices,'validate_runtime'), \
|
||
|
|
patch.object(native.member_tx,'run') as run:
|
||
|
|
adapter.healthcheck(4800)
|
||
|
|
run.assert_not_called()
|
||
|
|
|
||
|
|
def test_native_tcp_target_rejects_names_and_invalid_ports(self):
|
||
|
|
for host,port in [('example.com',3000),('127.0.0.1',True),('127.0.0.1',0),('127.0.0.1',65536),('127.0.0.1','3000')]:
|
||
|
|
with self.subTest(host=host,port=port),self.assertRaises(ValueError):
|
||
|
|
native.tcp_target({'host':host,'port':port})
|
||
|
|
|
||
|
|
def test_restore_retains_only_private_tcp_probes_with_valid_ports(self):
|
||
|
|
contract={'schema':1,'dependencies':[{'vmid':4801,'label':'helper',
|
||
|
|
'healthcheck':{'type':'tcp','host':'10.77.20.31','port':9998,'timeout_seconds':120}}]}
|
||
|
|
self.assertTrue(recovery.valid_contract(contract,{4801}))
|
||
|
|
for changes in ({'host':'192.168.1.1'},{'host':'localhost'},{'port':False},{'port':65536}):
|
||
|
|
invalid=copy.deepcopy(contract);invalid['dependencies'][0]['healthcheck'].update(changes)
|
||
|
|
self.assertFalse(recovery.valid_contract(invalid,{4801}))
|
||
|
|
|
||
|
|
def test_hook_tcp_probe_checks_connection_not_http_status(self):
|
||
|
|
text=(ROOT/'remote/stack_dependency_hook.sh').read_text()
|
||
|
|
functions=text[text.index('dependency_is_healthy() {'):text.index('\nstart_dependencies()')]
|
||
|
|
with socket.socket() as server:
|
||
|
|
server.bind(('127.0.0.1',0));server.listen()
|
||
|
|
port=server.getsockname()[1]
|
||
|
|
command=functions+'\ndependency_is_healthy 4801 \'{"type":"tcp","host":"127.0.0.1","port":'+str(port)+'}\''
|
||
|
|
result=subprocess.run(['bash','-c',command],text=True,capture_output=True)
|
||
|
|
self.assertEqual(result.returncode,0,result.stderr)
|
||
|
|
failed=subprocess.run(['bash','-c',command],text=True,capture_output=True)
|
||
|
|
self.assertNotEqual(failed.returncode,0)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__=='__main__':unittest.main()
|