"""Test docker events monitor.""" import asyncio from typing import Any from unittest.mock import patch from aiodocker.containers import DockerContainer from awesomeversion import AwesomeVersion import pytest from supervisor.bus import Bus from supervisor.const import BusEvent from supervisor.coresys import CoreSys from supervisor.docker.const import ContainerState from supervisor.docker.monitor import DockerContainerStateEvent @pytest.mark.parametrize( "event,expected", [ ( { "Type": "container", "Action": "start", "Actor": {"Attributes": {"supervisor_managed": ""}}, }, ContainerState.RUNNING, ), ( { "Type": "container", "Action": "die", "Actor": {"Attributes": {"supervisor_managed": "", "exitCode": "0"}}, }, ContainerState.STOPPED, ), ( { "Type": "container", "Action": "die", "Actor": {"Attributes": {"supervisor_managed": "", "exitCode": "137"}}, }, ContainerState.FAILED, ), ( { "Type": "container", "Action": "health_status: healthy", "Actor": {"Attributes": {"supervisor_managed": ""}}, }, ContainerState.HEALTHY, ), ( { "Type": "container", "Action": "health_status: unhealthy", "Actor": {"Attributes": {"supervisor_managed": ""}}, }, ContainerState.UNHEALTHY, ), ( { "Type": "container", "Action": "exec_die", "Actor": {"Attributes": {"supervisor_managed": ""}}, }, None, ), ( { "Type": "container", "Action": "start", "Actor": {"Attributes": {}}, }, None, ), ( { "Type": "network", "Action": "start", "Actor": {"Attributes": {}}, }, None, ), ], ) async def test_events( coresys: CoreSys, event: dict[str, Any], expected: ContainerState | None ): """Test events created from docker events.""" event["Actor"]["Attributes"]["name"] = "some_container" event["Actor"]["ID"] = "abc123" event["time"] = 123 with patch.object( Bus, "fire_event", return_value=[coresys.create_task(asyncio.sleep(0))] ) as fire_event: await coresys.docker.docker.events.channel.publish(event) await asyncio.sleep(0) await coresys.docker.monitor.unload() if expected: fire_event.assert_called_once_with( BusEvent.DOCKER_CONTAINER_STATE_CHANGE, DockerContainerStateEvent("some_container", expected, "abc123", 123), ) else: fire_event.assert_not_called() async def test_unlabeled_container(coresys: CoreSys, container: DockerContainer): """Test attaching to unlabeled container is still watched.""" container.id = "abc123" container.show.return_value = { "Name": "homeassistant", "Id": "abc123", "State": {"Status": "running"}, "Config": {}, } await coresys.homeassistant.core.instance.attach(AwesomeVersion("2022.7.3")) with patch.object( Bus, "fire_event", return_value=[coresys.create_task(asyncio.sleep(0))] ) as fire_event: await coresys.docker.docker.events.channel.publish( { "time": 123, "Type": "container", "Action": "die", "Actor": { "ID": "abc123", "Attributes": {"name": "homeassistant", "exitCode": "137"}, }, } ) await coresys.docker.monitor.unload() fire_event.assert_called_once_with( BusEvent.DOCKER_CONTAINER_STATE_CHANGE, DockerContainerStateEvent( "homeassistant", ContainerState.FAILED, "abc123", 123 ), )