mirror of
https://github.com/home-assistant/core.git
synced 2026-09-24 07:25:52 -05:00
Portainer add prune unused images (#160137)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -65,6 +65,7 @@ def mock_portainer_client() -> Generator[AsyncMock]:
|
||||
)
|
||||
|
||||
client.restart_container = AsyncMock(return_value=None)
|
||||
client.images_prune = AsyncMock(return_value=None)
|
||||
|
||||
yield client
|
||||
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
}),
|
||||
'original_device_class': <ButtonDeviceClass.RESTART: 'restart'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Restart Container',
|
||||
'original_name': 'Restart container',
|
||||
'platform': 'portainer',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'translation_key': 'restart_container',
|
||||
'unique_id': 'portainer_test_entry_123_focused_einstein_restart',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -38,7 +38,7 @@
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'restart',
|
||||
'friendly_name': 'focused_einstein Restart Container',
|
||||
'friendly_name': 'focused_einstein Restart container',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.focused_einstein_restart_container',
|
||||
@@ -73,12 +73,12 @@
|
||||
}),
|
||||
'original_device_class': <ButtonDeviceClass.RESTART: 'restart'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Restart Container',
|
||||
'original_name': 'Restart container',
|
||||
'platform': 'portainer',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'translation_key': 'restart_container',
|
||||
'unique_id': 'portainer_test_entry_123_funny_chatelet_restart',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -87,7 +87,7 @@
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'restart',
|
||||
'friendly_name': 'funny_chatelet Restart Container',
|
||||
'friendly_name': 'funny_chatelet Restart container',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.funny_chatelet_restart_container',
|
||||
@@ -97,6 +97,55 @@
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_button_entities_snapshot[button.my_environment_prune_unused_images-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'button',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'button.my_environment_prune_unused_images',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <ButtonDeviceClass.RESTART: 'restart'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Prune unused images',
|
||||
'platform': 'portainer',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'images_prune',
|
||||
'unique_id': 'portainer_test_entry_123_1_images_prune',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_all_button_entities_snapshot[button.my_environment_prune_unused_images-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'restart',
|
||||
'friendly_name': 'my-environment Prune unused images',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.my_environment_prune_unused_images',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
})
|
||||
# ---
|
||||
# name: test_all_button_entities_snapshot[button.practical_morse_restart_container-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
@@ -122,12 +171,12 @@
|
||||
}),
|
||||
'original_device_class': <ButtonDeviceClass.RESTART: 'restart'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Restart Container',
|
||||
'original_name': 'Restart container',
|
||||
'platform': 'portainer',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'translation_key': 'restart_container',
|
||||
'unique_id': 'portainer_test_entry_123_practical_morse_restart',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -136,7 +185,7 @@
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'restart',
|
||||
'friendly_name': 'practical_morse Restart Container',
|
||||
'friendly_name': 'practical_morse Restart container',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.practical_morse_restart_container',
|
||||
@@ -171,12 +220,12 @@
|
||||
}),
|
||||
'original_device_class': <ButtonDeviceClass.RESTART: 'restart'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Restart Container',
|
||||
'original_name': 'Restart container',
|
||||
'platform': 'portainer',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'translation_key': 'restart_container',
|
||||
'unique_id': 'portainer_test_entry_123_serene_banach_restart',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -185,7 +234,7 @@
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'restart',
|
||||
'friendly_name': 'serene_banach Restart Container',
|
||||
'friendly_name': 'serene_banach Restart container',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.serene_banach_restart_container',
|
||||
@@ -220,12 +269,12 @@
|
||||
}),
|
||||
'original_device_class': <ButtonDeviceClass.RESTART: 'restart'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Restart Container',
|
||||
'original_name': 'Restart container',
|
||||
'platform': 'portainer',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'translation_key': 'restart_container',
|
||||
'unique_id': 'portainer_test_entry_123_stoic_turing_restart',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
@@ -234,7 +283,7 @@
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'restart',
|
||||
'friendly_name': 'stoic_turing Restart Container',
|
||||
'friendly_name': 'stoic_turing Restart container',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.stoic_turing_restart_container',
|
||||
|
||||
@@ -49,7 +49,7 @@ async def test_all_button_entities_snapshot(
|
||||
("restart", "restart_container"),
|
||||
],
|
||||
)
|
||||
async def test_buttons(
|
||||
async def test_buttons_containers(
|
||||
hass: HomeAssistant,
|
||||
mock_portainer_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
@@ -81,7 +81,7 @@ async def test_buttons(
|
||||
(PortainerTimeoutError("timeout"), "restart_container"),
|
||||
],
|
||||
)
|
||||
async def test_buttons_exceptions(
|
||||
async def test_buttons_containers_exceptions(
|
||||
hass: HomeAssistant,
|
||||
mock_portainer_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
@@ -104,3 +104,63 @@ async def test_buttons_exceptions(
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("action", "client_method"),
|
||||
[
|
||||
("prune", "images_prune"),
|
||||
],
|
||||
)
|
||||
async def test_buttons_endpoint(
|
||||
hass: HomeAssistant,
|
||||
mock_portainer_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
action: str,
|
||||
client_method: str,
|
||||
) -> None:
|
||||
"""Test pressing a Portainer endpoint action button triggers client call. Click, click!"""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
entity_id = f"button.my_environment_{action}_unused_images"
|
||||
method_mock = getattr(mock_portainer_client, client_method)
|
||||
pre_calls = len(method_mock.mock_calls)
|
||||
|
||||
await hass.services.async_call(
|
||||
BUTTON_DOMAIN,
|
||||
SERVICE_PRESS,
|
||||
{ATTR_ENTITY_ID: entity_id},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert len(method_mock.mock_calls) == pre_calls + 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("exception", "client_method"),
|
||||
[
|
||||
(PortainerAuthenticationError("auth"), "images_prune"),
|
||||
(PortainerConnectionError("conn"), "images_prune"),
|
||||
(PortainerTimeoutError("timeout"), "images_prune"),
|
||||
],
|
||||
)
|
||||
async def test_buttons_endpoints_exceptions(
|
||||
hass: HomeAssistant,
|
||||
mock_portainer_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
exception: Exception,
|
||||
client_method: str,
|
||||
) -> None:
|
||||
"""Test that Portainer buttons, but this time when they will do boom for sure."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
method_mock = getattr(mock_portainer_client, client_method)
|
||||
method_mock.side_effect = exception
|
||||
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
BUTTON_DOMAIN,
|
||||
SERVICE_PRESS,
|
||||
{ATTR_ENTITY_ID: "button.my_environment_prune_unused_images"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user