Files

96 lines
4.4 KiB
Python
Raw Permalink Normal View History

"""Home Assistant OS is updated and modified like any other application."""
import json
import subprocess
import sys
import tempfile
from pathlib import Path
from unittest import TestCase
from unittest.mock import patch
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / 'remote'))
import oci_instance_transaction as transaction
HAOS = json.loads((ROOT / 'catalog/curated/haos-one.json').read_text())
CONFIG = (b'net0: name=eth0,bridge=vmbr0,firewall=1,host-managed=1,hwaddr=BC:24:11:D5:0F:FD,ip=dhcp,type=veth\n'
b'ostype: unmanaged\n')
ETH0 = b'2: eth0 inet 192.168.0.100/24 brd 192.168.0.255 scope global eth0\\ valid_lft forever\n'
class HaosCheckTests(TestCase):
def test_the_recipe_has_a_check_so_the_operation_is_not_refused(self):
check = transaction.effective_healthcheck(HAOS)
self.assertEqual(check, {'type': 'haos', 'timeout_seconds': 1200})
def test_the_check_is_left_to_the_installer_profile(self):
contract = transaction.with_default_healthcheck({'template': json.loads(json.dumps(HAOS))})
profile = contract['template']['proxmox']['installer_profile']
self.assertNotIn('startup_healthcheck', profile)
self.assertEqual(profile['haos_healthcheck'], {'timeout_seconds': 1200})
def run_commands(self, *args):
if args[:2] == ('pct', 'config'):
return CONFIG
if args[:2] == ('pct', 'status'):
return b'status: running\n'
if args[0] == 'lxc-attach':
return ETH0
raise AssertionError(args)
def test_the_container_answers_on_its_own_interface(self):
with patch.object(transaction, 'run', side_effect=self.run_commands):
self.assertEqual(transaction.own_addresses(121), ['192.168.0.100'])
def test_a_restored_container_passes_the_check_of_home_assistant(self):
import haos_healthcheck
urls = [{'label': 'Home Assistant', 'url': 'http://192.168.0.100:8123/'}]
with patch.object(transaction, 'run', side_effect=self.run_commands), \
patch.object(transaction, 'log'), \
patch.object(haos_healthcheck, 'wait_ready', return_value=urls) as wait:
self.assertEqual(transaction.healthcheck(121, HAOS), 'http://192.168.0.100:8123/')
wait.assert_called_once_with(121, '192.168.0.100', 1200)
def test_a_restored_container_that_does_not_pass_is_not_confirmed(self):
import haos_healthcheck
with patch.object(transaction, 'run', side_effect=self.run_commands), \
patch.object(transaction, 'log'), \
patch.object(haos_healthcheck, 'wait_ready', side_effect=RuntimeError('time is up')):
with self.assertRaises(ValueError):
transaction.healthcheck(121, HAOS)
class InstallerAddressTests(TestCase):
"""The installer takes the address of an interface of the container, not
the one of a bridge Docker created inside it."""
def address(self, listed, attach):
script = (ROOT / 'remote/install_oci.sh').read_text()
start = script.index('own_ipv4() {')
function = script[start:script.index('\n}\n', start) + 3]
with tempfile.TemporaryDirectory() as tmp:
for name, body in (('lxc-info', f'printf "{listed}"'),
('pct', 'echo "net0: name=eth0,bridge=vmbr0,ip=dhcp,type=veth"'),
('lxc-attach', attach)):
path = Path(tmp) / name
path.write_text(f'#!/bin/bash\n{body}\n')
path.chmod(0o755)
result = subprocess.run(['bash', '-c', f'PATH={tmp}:$PATH; VMID=121; {function}\nown_ipv4; echo "rc=$?"'],
capture_output=True, text=True)
return result.stdout.split()
def test_the_inner_bridges_are_skipped(self):
attach = 'echo "2: eth0 inet 192.168.0.100/24 brd 192.168.0.255 scope global eth0"'
self.assertEqual(self.address('172.30.232.1\\n172.30.32.1\\n192.168.0.100\\n', attach), ['192.168.0.100', 'rc=0'])
def test_no_address_yet_is_waited_for(self):
self.assertEqual(self.address('172.30.232.1\\n', 'true'), ['rc=0'])
def test_interfaces_that_cannot_be_read_leave_it_to_the_caller(self):
self.assertEqual(self.address('192.168.0.100\\n', 'exit 1'), ['rc=1'])
self.assertEqual(self.address('', 'true'), ['rc=1'])
if __name__ == '__main__':
import unittest
unittest.main()