Skip to content

Conversation

@cr7pt0gr4ph7
Copy link
Contributor

@cr7pt0gr4ph7 cr7pt0gr4ph7 commented Sep 8, 2025

Proposed change

Remove the arbitrary (and undocumented) restrictions on how lists and dicts can be nested within themselves and each other in addon config schemas, so e.g. the following is now allowed:

schema:
  filters:
    - conditions:
        - property: str
          condition: list(equal|not_equal)
          value: str
      actions:
        accept: bool?
        latency: int?

The only remaining restriction is that list-of-lists (field: [[str]]) are disallowed, because there's no way to represent them in the current encoding for UiOptions (and they can already be represented in a more self-documenting way: field: [{subfield: [str]}]).

The current documentation at https://developers.home-assistant.io/docs/add-ons/configuration#options--schema does not mention the restrictions, and as such does not require an update per-se.

A documentation PR has been created at home-assistant/developers.home-assistant#2778, but can also be applied independently of the current PR.

Related issues

There is discussion at #2640 about changing the way addon configuration schemas are defined, but that discussion is already 4 years old. Given that the configuration UI already bails out to raw YAML syntax for some more complex schemas like the one down below, it does not worsen the current situation to simply loosen the current restrictions:

schema:
  filters:
    - conditions:
        - str?
      accept: bool?
      latency: int?

The only other currently available option for addons requiring more complex schemas is to forego Supervisor-side validation entirely.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality to the supervisor)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Ruff (ruff format supervisor tests)
  • Tests have been added to verify that the new code works.

If API endpoints or add-on configuration are added/changed:

  • Documentation added/updated for developers.home-assistant.io
  • CLI updated (if necessary) Not necessary, the JSON for the addon options that is exposed by the CLI is not changed.
  • Client library updated (if necessary) Not necessary, the JSON for the addon options that is exposed by the client library is not changed.

@sentry
Copy link

sentry bot commented Sep 8, 2025

🔍 Existing Issues For Review

Your pull request is modifying functions with the following pre-existing issues:

📄 File: supervisor/addons/options.py

Function Unhandled Issue
__call__ IndexError: no such group supervisor.api.utils.ap...
Event Count: 2

Did you find this useful? React with a 👍 or 👎

@cr7pt0gr4ph7 cr7pt0gr4ph7 changed the title Addon config nested schemas Allow deeply nested dicts and lists in addon config schemas Sep 8, 2025
@agners agners added the new-feature A new feature label Sep 8, 2025
@cr7pt0gr4ph7
Copy link
Contributor Author

The build issue on i386 is not related to this PR, but GitHub Container Registry returning 502 Bad Gateway when attempting to retrieve one of the base images.

@agners
Copy link
Member

agners commented Sep 8, 2025

Thanks for your PR!

There is discussion at #2640 about changing the way addon configuration schemas are defined, but that discussion is already 4 years old. Given that the configuration UI already bails out to raw YAML syntax for some more complex schemas like the one down below, it does not worsen the current situation to simply loosen the current restrictions:

True, but starting to support nested options with the current situation will create even more complex YAML configurations which people struggle to work with (e.g. see home-assistant/addons#4076).

The current configuration frontend is custom for add-ons. There is also the idea to make the config option compatible with Home Assistant Core Selectors (https://www.home-assistant.io/docs/blueprint/selectors/). This would allow to leverage existing frontend code.

@cr7pt0gr4ph7
Copy link
Contributor Author

cr7pt0gr4ph7 commented Sep 9, 2025

There is also the idea to make the config option compatible with Home Assistant Core Selectors (https://www.home-assistant.io/docs/blueprint/selectors/).

Reusing the Selectors infrastructure is a great idea, but would solve only a part of the problem - there's a reason why integrations have the whole voluptuous-based schema definition on top of that to support more complex nested data.

True, but starting to support nested options with the current situation will create even more complex YAML configurations which people struggle to work with (e.g. see home-assistant/addons#4076).

The complex configuration schemas are mostly born out of a necessity defined by the problem domain, so there's no way to avoid it in some cases.

There's currently no way to adequately map certain configuration patterns that have their valid uses:

  • Sections of related configuration options
  • Lists of composite entities containing fields themselves (e.g. lists of email filters that each have a list of a conditions and actions).
  • Components that must be exactly one of a number of fixed types - like:
    dns_provider:
      aws:
        access_key_id: str?
        secret_access_key: str?

The underlying form toolkit being used already supports the first and second point (via HaFormExpandableSchema and HaFormSelector/ObjectSelector), and could be extended to support the last point as well by adding HaFormUnionSchema, following the UI conventions already established by e.g. the automation/action editors. The code mapping from the addon schema to the HaFormSchema can also easily be extended.

See home-assistant/addons#4076

As an aside, wouldn't it be possible to display a warning in the UI when something like dns: { dns: ... } is detected?

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes arbitrary restrictions on how lists and dictionaries can be nested within addon configuration schemas, allowing for more complex and flexible schema definitions. The change maintains backward compatibility while enabling deeper nesting patterns that were previously disallowed.

Key changes:

  • Updated schema validation to allow recursive nesting of dicts and lists (except list-of-lists)
  • Refactored validation logic to use a unified _validate_element method for all types
  • Added comprehensive tests for complex nested schema scenarios

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
supervisor/addons/validate.py Updated SCHEMA_ELEMENT to support recursive nesting with vol.Self references
supervisor/addons/options.py Refactored validation methods to use unified _validate_element approach
tests/addons/test_options.py Added test for complex dict/list nested validation scenarios
tests/addons/test_config.py Added comprehensive schema validation tests covering various nesting patterns

@agners
Copy link
Member

agners commented Sep 12, 2025

There is also the idea to make the config option compatible with Home Assistant Core Selectors (https://www.home-assistant.io/docs/blueprint/selectors/).

Reusing the Selectors infrastructure is a great idea, but would solve only a part of the problem - there's a reason why integrations have the whole voluptuous-based schema definition on top of that to support more complex nested data.

True. But you could make the argument first moving to selectors infrastructure before adding more complexity to the code might make sense.

True, but starting to support nested options with the current situation will create even more complex YAML configurations which people struggle to work with (e.g. see home-assistant/addons#4076).

The complex configuration schemas are mostly born out of a necessity defined by the problem domain, so there's no way to avoid it in some cases.

Yeah that was my point, the lack of UI support causing problems today even with a single level of nesting. But given you've proposing to add proper UI support for nested (and deeply nested) configurations with options with home-assistant/frontend#26997, I am all for supporting deep nesting.

Also the PRs all look quite straight forward without too much additional complexity. So I am all for moving forward with your PRs.

There's currently no way to adequately map certain configuration patterns that have their valid uses:

  • Sections of related configuration options
  • Lists of composite entities containing fields themselves (e.g. lists of email filters that each have a list of a conditions and actions).
  • Components that must be exactly one of a number of fixed types - like:
    dns_provider:
      aws:
        access_key_id: str?
        secret_access_key: str?

The underlying form toolkit being used already supports the first and second point (via HaFormExpandableSchema and HaFormSelector/ObjectSelector), and could be extended to support the last point as well by adding HaFormUnionSchema, following the UI conventions already established by e.g. the automation/action editors. The code mapping from the addon schema to the HaFormSchema can also easily be extended.

Nice 👍

See home-assistant/addons#4076

As an aside, wouldn't it be possible to display a warning in the UI when something like dns: { dns: ... } is detected?

You mean a generic error, whenever a nested dict with the same key as the key is detected 🤔 I guess we could do this, but potentially some add-on actually requires such a nesting. Anyhow, I think with the UI support for nesting that won't be necessary 🎉 .

Copy link
Contributor

@mdegat01 mdegat01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI debate aside, this honestly feels like more of a bug fix then a new feature. I kind of doubt banning dictionaries in dictionaries was intentional. This looks a lot cleaner and more sensible, LGTM 👍

Copy link
Member

@agners agners left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you for your contribution 🙏 !

@agners agners merged commit ac9947d into home-assistant:main Sep 16, 2025
29 of 32 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Sep 18, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants