-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Portainer integration #129438
base: dev
Are you sure you want to change the base?
Add Portainer integration #129438
Conversation
Tested this out a bit and have some notes:
|
We now add
I also thought about it, but maybe for some people it's to difficult.
What do you mean exactly?
Solved |
I have it setup so navigating to https://home/portainer loads portainer (which is actually being hosted on 9443, but the redirect obscures that). Given the port is configurable, the integration shouldn't make assumptions about the port (I would add https:// if there's no protocol unless it's specifically 9000). If all that's needed is a URL then just have the configuration be a URL. People that use portainer already know how to access it via the URL so that should be easily available and less complicated than splitting it into hostname (with a protocol) and port |
During startup it gives a new error:
|
Setup works and shows the states of all the containers as expected. I tried stopping a container and it still shows as running in HA even a few minutes later while it shows as exited in portainer |
How long did you wait? |
Ok, I lowered that and it seems to be updating, guess I just didn't wait long enough. In that case it seems all good |
After the integration is added, I want to read out the settings in portainer and adjust the update interval in Home Assistant according to the setting in portainer. |
await self.async_set_unique_id(user_input[CONF_URL]) | ||
self._abort_if_unique_id_configured() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An URL is not a good unique id, can we find something unique in the API like an (unique) user id? Otherwise we need to use _abort_entries_match
"""The constants for the Portainer integration.""" | ||
|
||
DOMAIN = "portainer" | ||
NAME = "Portainer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name is unused i believe
type PortainerConfigEntry = ConfigEntry[PortainerDataUpdateCoordinator] | ||
|
||
|
||
class ContainerBaseEntity(CoordinatorEntity[PortainerDataUpdateCoordinator]): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a Portainer?
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
type PortainerConfigEntry = ConfigEntry[PortainerDataUpdateCoordinator] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already declared in init, delete one of those 2
CONTAINER_SENSOR_TYPES: tuple[ContainerSensorEntityDescription, ...] = ( | ||
ContainerSensorEntityDescription( | ||
key="container_state", | ||
translation_key="container_state", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
translation_key="container_state", | |
translation_key="container_state", | |
name=None, |
If the name is None, the name of the device will be the name of the entity
class ContainerSensorEntityDescription(SensorEntityDescription): | ||
"""Describes Portainer sensor entity.""" | ||
|
||
exists_fn: Callable[[NodeData], bool] = lambda _: True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused?
entity_reg = er.async_get(hass) | ||
for entity_entry in er.async_entries_for_config_entry( | ||
entity_reg, entry.entry_id | ||
): | ||
for container_name in removed_containers: | ||
for description in CONTAINER_SENSOR_TYPES: | ||
if entity_entry.unique_id.startswith( | ||
f"{node_id}-{container_name}-{description.key}" | ||
): | ||
_LOGGER.info("Deleting: %s", entity_entry.entity_id) | ||
entity_reg.async_remove(entity_entry.entity_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since all containers are their own device, we can just remove the device (or to be more specific, remove the config entry from the device)
self.entity_description = description | ||
# We use container name as unique id, because the container_id changes | ||
# with an update of the container | ||
self._attr_unique_id = f"{node_id}-{self.container_id}-{description.key}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self._attr_unique_id = f"{node_id}-{self.container_id}-{description.key}" | |
self._attr_unique_id = f"{node_id}-{container_id}-{description.key}" |
Is that comment correct?
# We use container name as unique id, because the container_id changes | ||
# with an update of the container |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be more useful to have that thing above container as sensor then? It's been a while since I used portainer, was it service? Would it be more useful to show that? Because containers come and go all the time. So when you start 2 containers, what happens with the unique id? Because the name is the same right?
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. |
Breaking change
Proposed change
Add Portainer integration.
In the first step it is possible to watch the state of the containers in your portainer instance.
In a second step we can add buttons to start, stop or restart the containers.
This integration uses the aiotainer library: https://github.com/Thomas55555/aiotainer
Type of change
Additional information
Checklist
ruff format homeassistant tests
)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest
.requirements_all.txt
.Updated by running
python3 -m script.gen_requirements_all
.To help with the load of incoming pull requests: