1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-02 08:26:41 +01:00

Add Swarm stack to Portainer (#164991)

This commit is contained in:
Erwin Douna
2026-03-11 18:14:05 +01:00
committed by GitHub
parent 2eb65ab314
commit c63ded3522
10 changed files with 869 additions and 0 deletions

View File

@@ -196,6 +196,7 @@ class PortainerCoordinator(DataUpdateCoordinator[dict[int, PortainerCoordinatorD
# Check if container belongs to a stack via docker compose label
stack_name: str | None = (
container.labels.get("com.docker.compose.project")
or container.labels.get("com.docker.stack.namespace")
if container.labels
else None
)

View File

@@ -168,5 +168,31 @@
],
"State": "running",
"Status": "Up 6 hours"
},
{
"Id": "ff31facfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf",
"Names": ["/dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05"],
"Image": "docker.io/lissy93/dashy:latest",
"ImageID": "sha256:7f8a4339a5c5d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782",
"Command": "node server",
"Created": "1739816096",
"Ports": [
{
"PrivatePort": 8080,
"PublicPort": 4000,
"Type": "tcp"
}
],
"Labels": {
"com.docker.stack.namespace": "dashy",
"com.docker.swarm.node.id": "nggd3w8ntk2ivzkka6ecprjkh",
"com.docker.swarm.service.id": "nk8zud67mpr6nyln0vhko65zb",
"com.docker.swarm.service.name": "dashy_dashy",
"com.docker.swarm.task": "",
"com.docker.swarm.task.id": "qgza68hnz4n1qvyz3iohynx05",
"com.docker.swarm.task.name": "dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05"
},
"State": "running",
"Status": "Up 3 hours"
}
]

View File

@@ -10,5 +10,17 @@
"CreatedBy": "admin",
"CreationDate": 1739700000,
"FromAppTemplate": false
},
{
"Id": 2,
"Name": "dashy",
"Type": 1,
"EndpointId": 1,
"Status": 1,
"EntryPoint": "docker-stack.yml",
"ProjectPath": "/data/compose/dashy",
"CreatedBy": "admin",
"CreationDate": 1739710000,
"FromAppTemplate": false
}
]

View File

@@ -1,4 +1,104 @@
# serializer version: 1
# name: test_all_entities[binary_sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_status-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': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_status',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Status',
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.RUNNING: 'running'>,
'original_icon': None,
'original_name': 'Status',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'status',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_status',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_status-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'running',
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 Status',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_status',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[binary_sensor.dashy_status-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': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.dashy_status',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Status',
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.RUNNING: 'running'>,
'original_icon': None,
'original_name': 'Status',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'status',
'unique_id': 'portainer_test_entry_123_2_stack_status',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.dashy_status-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'running',
'friendly_name': 'dashy Status',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.dashy_status',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[binary_sensor.focused_einstein_status-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@@ -1,4 +1,54 @@
# serializer version: 1
# name: test_all_button_entities_snapshot[button.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_restart_container-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.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_restart_container',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Restart container',
'options': dict({
}),
'original_device_class': <ButtonDeviceClass.RESTART: 'restart'>,
'original_icon': None,
'original_name': 'Restart container',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'restart_container',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_restart',
'unit_of_measurement': None,
})
# ---
# name: test_all_button_entities_snapshot[button.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_restart_container-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'restart',
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 Restart container',
}),
'context': <ANY>,
'entity_id': 'button.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_restart_container',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---
# name: test_all_button_entities_snapshot[button.focused_einstein_restart_container-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@@ -73,6 +73,15 @@
'state': 'running',
'status': 'Up 6 hours',
}),
dict({
'id': 'ff31facfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf',
'image': 'docker.io/lissy93/dashy:latest',
'names': list([
'/dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05',
]),
'state': 'running',
'status': 'Up 3 hours',
}),
]),
'endpoint': dict({
'public_url': 'docker.mydomain.tld:2375',

View File

@@ -146,6 +146,35 @@
'sw_version': None,
'via_device_id': <ANY>,
}),
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
'config_entries_subentries': <ANY>,
'configuration_url': 'https://127.0.0.1:9000/#!/1/docker/stacks/dashy',
'connections': set({
}),
'disabled_by': None,
'entry_type': None,
'hw_version': None,
'id': <ANY>,
'identifiers': set({
tuple(
'portainer',
'portainer_test_entry_123_1_stack_2',
),
}),
'labels': set({
}),
'manufacturer': 'Portainer',
'model': 'Stack',
'model_id': None,
'name': 'dashy',
'name_by_user': None,
'primary_config_entry': <ANY>,
'serial_number': None,
'sw_version': None,
'via_device_id': <ANY>,
}),
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
@@ -204,5 +233,34 @@
'sw_version': None,
'via_device_id': <ANY>,
}),
DeviceRegistryEntrySnapshot({
'area_id': None,
'config_entries': <ANY>,
'config_entries_subentries': <ANY>,
'configuration_url': 'https://127.0.0.1:9000/#!/1/docker/containers/ff31facfb3b3ed4cd362c1e88fc89a53908ad05fb3a4103bca3f9b28292d14bf',
'connections': set({
}),
'disabled_by': None,
'entry_type': <DeviceEntryType.SERVICE: 'service'>,
'hw_version': None,
'id': <ANY>,
'identifiers': set({
tuple(
'portainer',
'portainer_test_entry_123_1_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05',
),
}),
'labels': set({
}),
'manufacturer': 'Portainer',
'model': 'Container',
'model_id': None,
'name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05',
'name_by_user': None,
'primary_config_entry': <ANY>,
'serial_number': None,
'sw_version': None,
'via_device_id': <ANY>,
}),
])
# ---

View File

@@ -1,4 +1,466 @@
# serializer version: 1
# name: test_all_entities[sensor.dashy_containers-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.dashy_containers',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Containers',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Containers',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'stack_containers_count',
'unique_id': 'portainer_test_entry_123_2_stack_containers_count',
'unit_of_measurement': 'containers',
})
# ---
# name: test_all_entities[sensor.dashy_containers-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'dashy Containers',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': 'containers',
}),
'context': <ANY>,
'entity_id': 'sensor.dashy_containers',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1',
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_cpu_usage_total-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_cpu_usage_total',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'CPU usage total',
'options': dict({
'sensor': dict({
'suggested_display_precision': 2,
}),
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'CPU usage total',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'cpu_usage_total',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_cpu_usage_total',
'unit_of_measurement': '%',
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_cpu_usage_total-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 CPU usage total',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_cpu_usage_total',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0.0',
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_image-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': 'sensor',
'entity_category': None,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_image',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Image',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Image',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'image',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_image',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_image-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 Image',
}),
'context': <ANY>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_image',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'docker.io/lissy93/dashy:latest',
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_limit-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_limit',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Memory limit',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.MEGABYTES: 'MB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Memory limit',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'memory_limit',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_memory_limit',
'unit_of_measurement': <UnitOfInformation.MEGABYTES: 'MB'>,
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_limit-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 Memory limit',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfInformation.MEGABYTES: 'MB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_limit',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '67.108864',
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_usage-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_usage',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Memory usage',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfInformation.MEGABYTES: 'MB'>,
}),
}),
'original_device_class': <SensorDeviceClass.DATA_SIZE: 'data_size'>,
'original_icon': None,
'original_name': 'Memory usage',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'memory_usage',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_memory_usage',
'unit_of_measurement': <UnitOfInformation.MEGABYTES: 'MB'>,
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_usage-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'data_size',
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 Memory usage',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfInformation.MEGABYTES: 'MB'>,
}),
'context': <ANY>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_usage',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '6.537216',
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_usage_percentage-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_usage_percentage',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Memory usage percentage',
'options': dict({
'sensor': dict({
'suggested_display_precision': 2,
}),
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Memory usage percentage',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'memory_usage_percentage',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_memory_usage_percentage',
'unit_of_measurement': '%',
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_usage_percentage-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 Memory usage percentage',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_memory_usage_percentage',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '9.7412109375',
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_state-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'running',
'exited',
'paused',
'restarting',
'created',
'dead',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_state',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'State',
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'State',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'container_state',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_container_state',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_state-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 State',
'options': list([
'running',
'exited',
'paused',
'restarting',
'created',
'dead',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_state',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'running',
})
# ---
# name: test_all_entities[sensor.dashy_type-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'swarm',
'compose',
'kubernetes',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.dashy_type',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Type',
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Type',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'stack_type',
'unique_id': 'portainer_test_entry_123_2_stack_type',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[sensor.dashy_type-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
'friendly_name': 'dashy Type',
'options': list([
'swarm',
'compose',
'kubernetes',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.dashy_type',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'swarm',
})
# ---
# name: test_all_entities[sensor.focused_einstein_cpu_usage_total-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@@ -1,4 +1,104 @@
# serializer version: 1
# name: test_all_switch_entities_snapshot[switch.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_container-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': 'switch',
'entity_category': None,
'entity_id': 'switch.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_container',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Container',
'options': dict({
}),
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
'original_icon': None,
'original_name': 'Container',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'container',
'unique_id': 'portainer_test_entry_123_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05_container',
'unit_of_measurement': None,
})
# ---
# name: test_all_switch_entities_snapshot[switch.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_container-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'switch',
'friendly_name': 'dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05 Container',
}),
'context': <ANY>,
'entity_id': 'switch.dashy_dashy_1_qgza68hnz4n1qvyz3iohynx05_container',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_switch_entities_snapshot[switch.dashy_stack-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': 'switch',
'entity_category': None,
'entity_id': 'switch.dashy_stack',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Stack',
'options': dict({
}),
'original_device_class': <SwitchDeviceClass.SWITCH: 'switch'>,
'original_icon': None,
'original_name': 'Stack',
'platform': 'portainer',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'stack',
'unique_id': 'portainer_test_entry_123_2_stack',
'unit_of_measurement': None,
})
# ---
# name: test_all_switch_entities_snapshot[switch.dashy_stack-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'switch',
'friendly_name': 'dashy Stack',
}),
'context': <ANY>,
'entity_id': 'switch.dashy_stack',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_switch_entities_snapshot[switch.focused_einstein_container-entry]
EntityRegistryEntrySnapshot({
'aliases': set({

View File

@@ -183,3 +183,54 @@ async def test_device_registry(
device_registry, mock_config_entry.entry_id
)
assert device_entries == snapshot
async def test_container_stack_device_links(
hass: HomeAssistant,
mock_portainer_client: AsyncMock,
mock_config_entry: MockConfigEntry,
device_registry: dr.DeviceRegistry,
) -> None:
"""Test that stack-linked containers are nested under the correct stack device."""
await setup_integration(hass, mock_config_entry)
endpoint_device = device_registry.async_get_device(
identifiers={(DOMAIN, f"{mock_config_entry.entry_id}_1")}
)
assert endpoint_device is not None
dashy_stack_device = device_registry.async_get_device(
identifiers={(DOMAIN, f"{mock_config_entry.entry_id}_1_stack_2")}
)
assert dashy_stack_device is not None
assert dashy_stack_device.via_device_id == endpoint_device.id
webstack_device = device_registry.async_get_device(
identifiers={(DOMAIN, f"{mock_config_entry.entry_id}_1_stack_1")}
)
assert webstack_device is not None
assert webstack_device.via_device_id == endpoint_device.id
swarm_container_device = device_registry.async_get_device(
identifiers={
(
DOMAIN,
f"{mock_config_entry.entry_id}_1_dashy_dashy.1.qgza68hnz4n1qvyz3iohynx05",
)
}
)
assert swarm_container_device is not None
assert swarm_container_device.via_device_id == dashy_stack_device.id
compose_container_device = device_registry.async_get_device(
identifiers={(DOMAIN, f"{mock_config_entry.entry_id}_1_serene_banach")}
)
assert compose_container_device is not None
assert compose_container_device.via_device_id == webstack_device.id
standalone_container_device = device_registry.async_get_device(
identifiers={(DOMAIN, f"{mock_config_entry.entry_id}_1_focused_einstein")}
)
assert standalone_container_device is not None
assert standalone_container_device.via_device_id == endpoint_device.id