From f9037d5f6d87a1aa04cad08f0d63e873f9604432 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 1 Jun 2023 17:30:15 +0200 Subject: [PATCH] Add platform only config schema to nsw_fuel_station and ping (#93913) --- .../components/homeassistant/strings.json | 4 ++ .../components/nsw_fuel_station/__init__.py | 3 ++ homeassistant/components/ping/__init__.py | 3 ++ homeassistant/helpers/config_validation.py | 39 +++++++++++++++---- tests/helpers/test_config_validation.py | 25 ++++++++++++ 5 files changed, 66 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/homeassistant/strings.json b/homeassistant/components/homeassistant/strings.json index 74bfa16e471..0a41f9c7a99 100644 --- a/homeassistant/components/homeassistant/strings.json +++ b/homeassistant/components/homeassistant/strings.json @@ -15,6 +15,10 @@ "config_entry_only": { "title": "The {domain} integration does not support YAML configuration", "description": "The {domain} integration does not support configuration via YAML file. You may not notice any obvious issues with the integration, but any configuration settings defined in YAML are not actually applied.\n\nTo resolve this:\n\n1. If you've not already done so, [set up the integration]({add_integration}).\n\n2. Remove `{domain}:` from your YAML configuration file.\n\n3. Restart Home Assistant." + }, + "platform_only": { + "title": "The {domain} integration does not support YAML configuration under its own key", + "description": "The {domain} integration does not support configuration under its own key, it must be configured under its supported platforms.\n\nTo resolve this:\n\n1. Remove `{domain}:` from your YAML configuration file.\n\n2. Restart Home Assistant." } }, "system_health": { diff --git a/homeassistant/components/nsw_fuel_station/__init__.py b/homeassistant/components/nsw_fuel_station/__init__.py index 6d45104e5d3..818656779a3 100644 --- a/homeassistant/components/nsw_fuel_station/__init__.py +++ b/homeassistant/components/nsw_fuel_station/__init__.py @@ -8,6 +8,7 @@ import logging from nsw_fuel import FuelCheckClient, FuelCheckError, Station from homeassistant.core import HomeAssistant +from homeassistant.helpers import config_validation as cv from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed @@ -18,6 +19,8 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = "nsw_fuel_station" SCAN_INTERVAL = datetime.timedelta(hours=1) +CONFIG_SCHEMA = cv.platform_only_config_schema(DOMAIN) + async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the NSW Fuel Station platform.""" diff --git a/homeassistant/components/ping/__init__.py b/homeassistant/components/ping/__init__.py index b78702de54d..3ff36f2e283 100644 --- a/homeassistant/components/ping/__init__.py +++ b/homeassistant/components/ping/__init__.py @@ -6,6 +6,7 @@ import logging from icmplib import SocketPermissionError, ping as icmp_ping from homeassistant.core import HomeAssistant +from homeassistant.helpers import config_validation as cv from homeassistant.helpers.reload import async_setup_reload_service from homeassistant.helpers.typing import ConfigType @@ -13,6 +14,8 @@ from .const import DOMAIN, PING_PRIVS, PLATFORMS _LOGGER = logging.getLogger(__name__) +CONFIG_SCHEMA = cv.platform_only_config_schema(DOMAIN) + async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the ping integration.""" diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py index 7b8ece69392..01fa4c19561 100644 --- a/homeassistant/helpers/config_validation.py +++ b/homeassistant/helpers/config_validation.py @@ -1075,7 +1075,12 @@ def empty_config_schema(domain: str) -> Callable[[dict], dict]: return validator -def config_entry_only_config_schema(domain: str) -> Callable[[dict], dict]: +def _no_yaml_config_schema( + domain: str, + issue_base: str, + translation_key: str, + translation_placeholders: dict[str, str], +) -> Callable[[dict], dict]: """Return a config schema which logs if attempted to setup from YAML.""" module = inspect.getmodule(inspect.stack(context=0)[2].frame) @@ -1092,21 +1097,17 @@ def config_entry_only_config_schema(domain: str) -> Callable[[dict], dict]: # pylint: disable-next=import-outside-toplevel from .issue_registry import IssueSeverity, async_create_issue - add_integration = f"/_my_redirect/config_flow_start?domain={domain}" with contextlib.suppress(LookupError): hass = async_get_hass() async_create_issue( hass, HOMEASSISTANT_DOMAIN, - f"config_entry_only_{domain}", + f"{issue_base}_{domain}", is_fixable=False, issue_domain=domain, severity=IssueSeverity.ERROR, - translation_key="config_entry_only", - translation_placeholders={ - "domain": domain, - "add_integration": add_integration, - }, + translation_key=translation_key, + translation_placeholders={"domain": domain} | translation_placeholders, ) def validator(config: dict) -> dict: @@ -1124,6 +1125,28 @@ def config_entry_only_config_schema(domain: str) -> Callable[[dict], dict]: return validator +def config_entry_only_config_schema(domain: str) -> Callable[[dict], dict]: + """Return a config schema which logs if attempted to setup from YAML.""" + + return _no_yaml_config_schema( + domain, + "config_entry_only", + "config_entry_only", + {"add_integration": f"/_my_redirect/config_flow_start?domain={domain}"}, + ) + + +def platform_only_config_schema(domain: str) -> Callable[[dict], dict]: + """Return a config schema which logs if attempted to setup from YAML.""" + + return _no_yaml_config_schema( + domain, + "platform_only", + "platform_only", + {}, + ) + + PLATFORM_SCHEMA = vol.Schema( { vol.Required(CONF_PLATFORM): string, diff --git a/tests/helpers/test_config_validation.py b/tests/helpers/test_config_validation.py index b9b5f989cba..e29447a8688 100644 --- a/tests/helpers/test_config_validation.py +++ b/tests/helpers/test_config_validation.py @@ -1552,3 +1552,28 @@ def test_config_entry_only_schema_no_hass( assert expected_message in caplog.text issue_registry = ir.async_get(hass) assert not issue_registry.issues + + +def test_platform_only_schema( + hass: HomeAssistant, caplog: pytest.LogCaptureFixture +) -> None: + """Test config_entry_only_config_schema.""" + expected_issue = "platform_only_test_domain" + expected_message = ( + "The test_domain integration does not support YAML setup, please remove " + "it from your configuration" + ) + issue_registry = ir.async_get(hass) + + cv.platform_only_config_schema("test_domain")({}) + assert expected_message not in caplog.text + assert not issue_registry.async_get_issue(HOMEASSISTANT_DOMAIN, expected_issue) + + cv.platform_only_config_schema("test_domain")({"test_domain": {}}) + assert expected_message in caplog.text + assert issue_registry.async_get_issue(HOMEASSISTANT_DOMAIN, expected_issue) + issue_registry.async_delete(HOMEASSISTANT_DOMAIN, expected_issue) + + cv.platform_only_config_schema("test_domain")({"test_domain": {"foo": "bar"}}) + assert expected_message in caplog.text + assert issue_registry.async_get_issue(HOMEASSISTANT_DOMAIN, expected_issue)