Detect use of deprecated base_url (#35353)

* Detect use of deprecated base_url

* Update get_url helper

* Update core migration

* Migrate all tests
pull/35381/head
Franck Nijhof 2020-05-08 17:52:32 +02:00 committed by GitHub
parent 1be41b9de8
commit e56dd8ed50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 308 additions and 73 deletions

View File

@ -3,6 +3,7 @@ from ipaddress import ip_network
import logging
import os
import ssl
from traceback import extract_stack
from typing import Optional, cast
from aiohttp import web
@ -119,14 +120,66 @@ class ApiConfig:
host = host.rstrip("/")
if host.startswith(("http://", "https://")):
self.base_url = host
self.deprecated_base_url = host
elif use_ssl:
self.base_url = f"https://{host}"
self.deprecated_base_url = f"https://{host}"
else:
self.base_url = f"http://{host}"
self.deprecated_base_url = f"http://{host}"
if port is not None:
self.base_url += f":{port}"
self.deprecated_base_url += f":{port}"
@property
def base_url(self) -> str:
"""Proxy property to find caller of this deprecated property."""
found_frame = None
for frame in reversed(extract_stack()):
for path in ("custom_components/", "homeassistant/components/"):
try:
index = frame.filename.index(path)
# Skip webhook from the stack
if frame.filename[index:].startswith(
"homeassistant/components/webhook/"
):
continue
found_frame = frame
break
except ValueError:
continue
if found_frame is not None:
break
# Did not source from an integration? Hard error.
if found_frame is None:
raise RuntimeError(
"Detected use of deprecated `base_url` property in the Home Assistant core. Please report this issue."
)
# If a frame was found, it originated from an integration
if found_frame:
start = index + len(path)
end = found_frame.filename.index("/", start)
integration = found_frame.filename[start:end]
if path == "custom_components/":
extra = " to the custom component author"
else:
extra = ""
_LOGGER.warning(
"Detected use of deprecated `base_url` property, use `homeassistant.helpers.network.async_get_url` method instead. Please report issue%s for %s using this method at %s, line %s: %s",
extra,
integration,
found_frame.filename[index:],
found_frame.lineno,
found_frame.line.strip(),
)
return self.deprecated_base_url
async def async_setup(hass, config):

View File

@ -1463,7 +1463,7 @@ class Config:
if self.hass.config.api is None:
return
base_url = yarl.URL(self.hass.config.api.base_url)
base_url = yarl.URL(self.hass.config.api.deprecated_base_url)
# Check if this is an internal URL
if str(base_url.host).endswith(".local") or (

View File

@ -195,10 +195,10 @@ def _async_get_deprecated_base_url(
require_standard_port: bool = False,
) -> str:
"""Work with the deprecated `base_url`, used as fallback."""
if hass.config.api is None or not hass.config.api.base_url:
if hass.config.api is None or not hass.config.api.deprecated_base_url:
raise NoURLAvailableError
base_url = yarl.URL(hass.config.api.base_url)
base_url = yarl.URL(hass.config.api.deprecated_base_url)
# Rules that apply to both internal and external
if (
(allow_ip or not is_ip_address(str(base_url.host)))

View File

@ -1,13 +1,16 @@
"""Test Home Assistant Cast."""
from homeassistant.components.cast import home_assistant_cast
from homeassistant.config import async_process_ha_core_config
from tests.async_mock import Mock, patch
from tests.async_mock import patch
from tests.common import MockConfigEntry, async_mock_signal
async def test_service_show_view(hass):
"""Test we don't set app id in prod."""
hass.config.api = Mock(base_url="https://example.com")
await async_process_ha_core_config(
hass, {"external_url": "https://example.com"},
)
await home_assistant_cast.async_setup_ha_cast(hass, MockConfigEntry())
calls = async_mock_signal(hass, home_assistant_cast.SIGNAL_HASS_CAST_SHOW_VIEW)
@ -31,7 +34,9 @@ async def test_service_show_view(hass):
async def test_service_show_view_dashboard(hass):
"""Test casting a specific dashboard."""
hass.config.api = Mock(base_url="https://example.com")
await async_process_ha_core_config(
hass, {"external_url": "https://example.com"},
)
await home_assistant_cast.async_setup_ha_cast(hass, MockConfigEntry())
calls = async_mock_signal(hass, home_assistant_cast.SIGNAL_HASS_CAST_SHOW_VIEW)
@ -55,7 +60,9 @@ async def test_service_show_view_dashboard(hass):
async def test_use_cloud_url(hass):
"""Test that we fall back to cloud url."""
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"internal_url": "http://example.local:8123"},
)
hass.config.components.add("cloud")
await home_assistant_cast.async_setup_ha_cast(hass, MockConfigEntry())

View File

@ -6,11 +6,10 @@ import pytest
from homeassistant import data_entry_flow
from homeassistant.components import dialogflow, intent_script
from homeassistant.config import async_process_ha_core_config
from homeassistant.core import callback
from homeassistant.setup import async_setup_component
from tests.async_mock import Mock
SESSION_ID = "a9b84cec-46b6-484e-8f31-f65dba03ae6d"
INTENT_ID = "c6a74079-a8f0-46cd-b372-5a934d23591c"
INTENT_NAME = "tests"
@ -79,7 +78,10 @@ async def fixture(hass, aiohttp_client):
},
)
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"internal_url": "http://example.local:8123"},
)
result = await hass.config_entries.flow.async_init(
"dialogflow", context={"source": "user"}
)

View File

@ -4,6 +4,7 @@ import pytest
from homeassistant import data_entry_flow
from homeassistant.components import zone
from homeassistant.components.geofency import CONF_MOBILE_BEACONS, DOMAIN
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import (
HTTP_OK,
HTTP_UNPROCESSABLE_ENTITY,
@ -14,7 +15,7 @@ from homeassistant.setup import async_setup_component
from homeassistant.util import slugify
# pylint: disable=redefined-outer-name
from tests.async_mock import Mock, patch
from tests.async_mock import patch
HOME_LATITUDE = 37.239622
HOME_LONGITUDE = -115.815811
@ -148,7 +149,9 @@ async def setup_zones(loop, hass):
@pytest.fixture
async def webhook_id(hass, geofency_client):
"""Initialize the Geofency component and get the webhook_id."""
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"internal_url": "http://example.local:8123"},
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}
)

View File

@ -8,6 +8,7 @@ from homeassistant.components.google_assistant.const import ( # noqa: F401
EVENT_COMMAND_RECEIVED,
NOT_EXPOSE_LOCAL,
)
from homeassistant.config import async_process_ha_core_config
from homeassistant.setup import async_setup_component
from homeassistant.util import dt
@ -24,7 +25,11 @@ from tests.common import (
async def test_google_entity_sync_serialize_with_local_sdk(hass):
"""Test sync serialize attributes of a GoogleEntity."""
hass.states.async_set("light.ceiling_lights", "off")
hass.config.api = Mock(port=1234, use_ssl=True, base_url="https://hostname:1234")
hass.config.api = Mock(port=1234, use_ssl=True)
await async_process_ha_core_config(
hass, {"external_url": "https://hostname:1234"},
)
hass.http = Mock(server_port=1234)
config = MockConfig(
hass=hass,

View File

@ -5,6 +5,7 @@ from homeassistant import data_entry_flow
from homeassistant.components import gpslogger, zone
from homeassistant.components.device_tracker import DOMAIN as DEVICE_TRACKER_DOMAIN
from homeassistant.components.gpslogger import DOMAIN, TRACKER_UPDATE
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import (
HTTP_OK,
HTTP_UNPROCESSABLE_ENTITY,
@ -14,7 +15,7 @@ from homeassistant.const import (
from homeassistant.helpers.dispatcher import DATA_DISPATCHER
from homeassistant.setup import async_setup_component
from tests.async_mock import Mock, patch
from tests.async_mock import patch
HOME_LATITUDE = 37.239622
HOME_LONGITUDE = -115.815811
@ -62,7 +63,9 @@ async def setup_zones(loop, hass):
@pytest.fixture
async def webhook_id(hass, gpslogger_client):
"""Initialize the GPSLogger component and get the webhook_id."""
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"internal_url": "http://example.local:8123"},
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}
)

View File

@ -3,11 +3,13 @@ from ipaddress import ip_network
import logging
import unittest
import pytest
import homeassistant.components.http as http
from homeassistant.setup import async_setup_component
from homeassistant.util.ssl import server_context_intermediate, server_context_modern
from tests.async_mock import patch
from tests.async_mock import Mock, patch
class TestView(http.HomeAssistantView):
@ -271,3 +273,127 @@ async def test_storing_config(hass, aiohttp_client, aiohttp_unused_port):
restored["trusted_proxies"][0] = ip_network(restored["trusted_proxies"][0])
assert restored == http.HTTP_SCHEMA(config)
async def test_use_of_base_url(hass):
"""Test detection base_url usage when called without integration context."""
await async_setup_component(hass, "http", {"http": {}})
with patch(
"homeassistant.components.http.extract_stack",
return_value=[
Mock(
filename="/home/frenck/homeassistant/core.py",
lineno="21",
line="do_something()",
),
Mock(
filename="/home/frenck/homeassistant/core.py",
lineno="42",
line="url = hass.config.api.base_url",
),
Mock(
filename="/home/frenck/example/client.py",
lineno="21",
line="something()",
),
],
), pytest.raises(RuntimeError):
hass.config.api.base_url
async def test_use_of_base_url_integration(hass, caplog):
"""Test detection base_url usage when called with integration context."""
await async_setup_component(hass, "http", {"http": {}})
with patch(
"homeassistant.components.http.extract_stack",
return_value=[
Mock(
filename="/home/frenck/homeassistant/core.py",
lineno="21",
line="do_something()",
),
Mock(
filename="/home/frenck/homeassistant/components/example/__init__.py",
lineno="42",
line="url = hass.config.api.base_url",
),
Mock(
filename="/home/frenck/example/client.py",
lineno="21",
line="something()",
),
],
):
assert hass.config.api.base_url == "http://127.0.0.1:8123"
assert (
"Detected use of deprecated `base_url` property, use `homeassistant.helpers.network.async_get_url` method instead. Please report issue for example using this method at homeassistant/components/example/__init__.py, line 42: url = hass.config.api.base_url"
in caplog.text
)
async def test_use_of_base_url_integration_webhook(hass, caplog):
"""Test detection base_url usage when called with integration context."""
await async_setup_component(hass, "http", {"http": {}})
with patch(
"homeassistant.components.http.extract_stack",
return_value=[
Mock(
filename="/home/frenck/homeassistant/core.py",
lineno="21",
line="do_something()",
),
Mock(
filename="/home/frenck/homeassistant/components/example/__init__.py",
lineno="42",
line="url = hass.config.api.base_url",
),
Mock(
filename="/home/frenck/homeassistant/components/webhook/__init__.py",
lineno="42",
line="return async_get_url(hass)",
),
Mock(
filename="/home/frenck/example/client.py",
lineno="21",
line="something()",
),
],
):
assert hass.config.api.base_url == "http://127.0.0.1:8123"
assert (
"Detected use of deprecated `base_url` property, use `homeassistant.helpers.network.async_get_url` method instead. Please report issue for example using this method at homeassistant/components/example/__init__.py, line 42: url = hass.config.api.base_url"
in caplog.text
)
async def test_use_of_base_url_custom_component(hass, caplog):
"""Test detection base_url usage when called with custom component context."""
await async_setup_component(hass, "http", {"http": {}})
with patch(
"homeassistant.components.http.extract_stack",
return_value=[
Mock(
filename="/home/frenck/homeassistant/core.py",
lineno="21",
line="do_something()",
),
Mock(
filename="/home/frenck/.homeassistant/custom_components/example/__init__.py",
lineno="42",
line="url = hass.config.api.base_url",
),
Mock(
filename="/home/frenck/example/client.py",
lineno="21",
line="something()",
),
],
):
assert hass.config.api.base_url == "http://127.0.0.1:8123"
assert (
"Detected use of deprecated `base_url` property, use `homeassistant.helpers.network.async_get_url` method instead. Please report issue to the custom component author for example using this method at custom_components/example/__init__.py, line 42: url = hass.config.api.base_url"
in caplog.text
)

View File

@ -5,11 +5,12 @@ from homeassistant import data_entry_flow
from homeassistant.components import locative
from homeassistant.components.device_tracker import DOMAIN as DEVICE_TRACKER_DOMAIN
from homeassistant.components.locative import DOMAIN, TRACKER_UPDATE
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import HTTP_OK, HTTP_UNPROCESSABLE_ENTITY
from homeassistant.helpers.dispatcher import DATA_DISPATCHER
from homeassistant.setup import async_setup_component
from tests.async_mock import Mock, patch
from tests.async_mock import patch
# pylint: disable=redefined-outer-name
@ -33,7 +34,9 @@ async def locative_client(loop, hass, hass_client):
@pytest.fixture
async def webhook_id(hass, locative_client):
"""Initialize the Geofency component and get the webhook_id."""
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"internal_url": "http://example.local:8123"},
)
result = await hass.config_entries.flow.async_init(
"locative", context={"source": "user"}
)

View File

@ -6,12 +6,11 @@ import pytest
from homeassistant import data_entry_flow
from homeassistant.components import mailgun, webhook
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import CONF_API_KEY, CONF_DOMAIN
from homeassistant.core import callback
from homeassistant.setup import async_setup_component
from tests.async_mock import Mock
API_KEY = "abc123"
@ -31,7 +30,9 @@ async def webhook_id_with_api_key(hass):
{mailgun.DOMAIN: {CONF_API_KEY: API_KEY, CONF_DOMAIN: "example.com"}},
)
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"internal_url": "http://example.local:8123"},
)
result = await hass.config_entries.flow.async_init(
"mailgun", context={"source": "user"}
)
@ -48,7 +49,9 @@ async def webhook_id_without_api_key(hass):
"""Initialize the Mailgun component and get the webhook_id w/o API key."""
await async_setup_component(hass, mailgun.DOMAIN, {})
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"internal_url": "http://example.local:8123"},
)
result = await hass.config_entries.flow.async_init(
"mailgun", context={"source": "user"}
)

View File

@ -9,7 +9,7 @@ from homeassistant.config import async_process_ha_core_config
from homeassistant.const import CONF_WEBHOOK_ID
from homeassistant.setup import async_setup_component
from tests.async_mock import Mock, patch
from tests.async_mock import patch
from tests.common import MockConfigEntry
CONF_WEBHOOK_URL = "webhook_url"
@ -47,9 +47,11 @@ def mock_not_supports_encryption():
yield
def init_config_flow(hass):
async def init_config_flow(hass):
"""Init a configuration flow."""
hass.config.api = Mock(base_url=BASE_URL)
await async_process_ha_core_config(
hass, {"external_url": BASE_URL},
)
flow = config_flow.OwnTracksFlow()
flow.hass = hass
return flow
@ -57,7 +59,7 @@ def init_config_flow(hass):
async def test_user(hass, webhook_id, secret):
"""Test user step."""
flow = init_config_flow(hass)
flow = await init_config_flow(hass)
result = await flow.async_step_user()
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
@ -74,7 +76,7 @@ async def test_user(hass, webhook_id, secret):
async def test_import(hass, webhook_id, secret):
"""Test import step."""
flow = init_config_flow(hass)
flow = await init_config_flow(hass)
result = await flow.async_step_import({})
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
@ -99,7 +101,7 @@ async def test_import_setup(hass):
async def test_abort_if_already_setup(hass):
"""Test that we can't add more than one instance."""
flow = init_config_flow(hass)
flow = await init_config_flow(hass)
MockConfigEntry(domain=DOMAIN, data={}).add_to_hass(hass)
assert hass.config_entries.async_entries(DOMAIN)
@ -117,7 +119,7 @@ async def test_abort_if_already_setup(hass):
async def test_user_not_supports_encryption(hass, not_supports_encryption):
"""Test user step."""
flow = init_config_flow(hass)
flow = await init_config_flow(hass)
result = await flow.async_step_user({})
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY

View File

@ -37,6 +37,7 @@ from homeassistant.components.smartthings.const import (
STORAGE_KEY,
STORAGE_VERSION,
)
from homeassistant.config import async_process_ha_core_config
from homeassistant.config_entries import CONN_CLASS_CLOUD_PUSH, SOURCE_USER, ConfigEntry
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_WEBHOOK_ID
from homeassistant.setup import async_setup_component
@ -73,8 +74,10 @@ async def setup_platform(hass, platform: str, *, devices=None, scenes=None):
async def setup_component(hass, config_file, hass_storage):
"""Load the SmartThing component."""
hass_storage[STORAGE_KEY] = {"data": config_file, "version": STORAGE_VERSION}
await async_process_ha_core_config(
hass, {"external_url": "https://test.local"},
)
await async_setup_component(hass, "smartthings", {})
hass.config.api.base_url = "https://test.local"
def _create_location():
@ -97,7 +100,7 @@ def locations_fixture(location):
@pytest.fixture(name="app")
def app_fixture(hass, config_file):
async def app_fixture(hass, config_file):
"""Fixture for a single app."""
app = Mock(AppEntity)
app.app_name = APP_NAME_PREFIX + str(uuid4())
@ -105,7 +108,7 @@ def app_fixture(hass, config_file):
app.app_type = "WEBHOOK_SMART_APP"
app.classifications = [CLASSIFICATION_AUTOMATION]
app.display_name = "Home Assistant"
app.description = f"{hass.config.location_name} at {hass.config.api.base_url}"
app.description = f"{hass.config.location_name} at https://test.local"
app.single_instance = True
app.webhook_target_url = webhook.async_generate_url(
hass, hass.data[DOMAIN][CONF_WEBHOOK_ID]

View File

@ -15,6 +15,7 @@ from homeassistant.components.smartthings.const import (
CONF_OAUTH_CLIENT_SECRET,
DOMAIN,
)
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import (
CONF_ACCESS_TOKEN,
HTTP_FORBIDDEN,
@ -417,9 +418,10 @@ async def test_entry_created_with_cloudhook(
async def test_invalid_webhook_aborts(hass):
"""Test flow aborts if webhook is invalid."""
hass.config.api.base_url = "http://0.0.0.0"
# Webhook confirmation shown
await async_process_ha_core_config(
hass, {"external_url": "http://example.local:8123"},
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}
)

View File

@ -16,6 +16,7 @@ from homeassistant.components.smartthings.const import (
SIGNAL_SMARTTHINGS_UPDATE,
SUPPORTED_PLATFORMS,
)
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import HTTP_FORBIDDEN, HTTP_INTERNAL_SERVER_ERROR
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.dispatcher import async_dispatcher_connect
@ -116,7 +117,9 @@ async def test_base_url_no_longer_https_does_not_load(
hass, config_entry, app, smartthings_mock
):
"""Test base_url no longer valid creates a new flow."""
hass.config.api.base_url = "http://0.0.0.0"
await async_process_ha_core_config(
hass, {"external_url": "http://example.local:8123"},
)
config_entry.add_to_hass(hass)
smartthings_mock.app.return_value = app
@ -218,7 +221,6 @@ async def test_config_entry_loads_unconnected_cloud(
"""Test entry loads during startup when cloud isn't connected."""
config_entry.add_to_hass(hass)
hass.data[DOMAIN][CONF_CLOUDHOOK_URL] = "https://test.cloud"
hass.config.api.base_url = "http://0.0.0.0"
smartthings_mock.app.return_value = app
smartthings_mock.installed_app.return_value = installed_app
smartthings_mock.devices.return_value = [device]

View File

@ -5,6 +5,7 @@ from homeassistant import data_entry_flow
from homeassistant.components import traccar, zone
from homeassistant.components.device_tracker import DOMAIN as DEVICE_TRACKER_DOMAIN
from homeassistant.components.traccar import DOMAIN, TRACKER_UPDATE
from homeassistant.config import async_process_ha_core_config
from homeassistant.const import (
HTTP_OK,
HTTP_UNPROCESSABLE_ENTITY,
@ -14,7 +15,7 @@ from homeassistant.const import (
from homeassistant.helpers.dispatcher import DATA_DISPATCHER
from homeassistant.setup import async_setup_component
from tests.async_mock import Mock, patch
from tests.async_mock import patch
HOME_LATITUDE = 37.239622
HOME_LONGITUDE = -115.815811
@ -23,7 +24,6 @@ HOME_LONGITUDE = -115.815811
@pytest.fixture(autouse=True)
def mock_dev_track(mock_device_tracker_conf):
"""Mock device tracker config loading."""
pass
@pytest.fixture(name="client")
@ -60,7 +60,9 @@ async def setup_zones(loop, hass):
@pytest.fixture(name="webhook_id")
async def webhook_id_fixture(hass, client):
"""Initialize the Traccar component and get the webhook_id."""
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"external_url": "http://example.com"},
)
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "user"}
)

View File

@ -1,10 +1,9 @@
"""Test the webhook component."""
import pytest
from homeassistant.config import async_process_ha_core_config
from homeassistant.setup import async_setup_component
from tests.async_mock import Mock
@pytest.fixture
def mock_client(hass, hass_client):
@ -37,7 +36,9 @@ async def test_unregistering_webhook(hass, mock_client):
async def test_generate_webhook_url(hass):
"""Test we generate a webhook url correctly."""
hass.config.api = Mock(base_url="https://example.com")
await async_process_ha_core_config(
hass, {"external_url": "https://example.com"},
)
url = hass.components.webhook.async_generate_url("some_id")
assert url == "https://example.com/api/webhook/some_id"

View File

@ -2,6 +2,7 @@
import pytest
from homeassistant import config_entries, data_entry_flow, setup
from homeassistant.config import async_process_ha_core_config
from homeassistant.helpers import config_entry_flow
from tests.async_mock import Mock, patch
@ -232,7 +233,9 @@ async def test_webhook_config_flow_registers_webhook(hass, webhook_flow_conf):
flow = config_entries.HANDLERS["test_single"]()
flow.hass = hass
hass.config.api = Mock(base_url="http://example.com")
await async_process_ha_core_config(
hass, {"external_url": "https://example.com"},
)
result = await flow.async_step_user(user_input={})
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY

View File

@ -6,6 +6,7 @@ import time
import pytest
from homeassistant import config_entries, data_entry_flow, setup
from homeassistant.config import async_process_ha_core_config
from homeassistant.helpers import config_entry_oauth2_flow
from tests.async_mock import patch
@ -124,7 +125,9 @@ async def test_abort_if_authorization_timeout(hass, flow_handler, local_impl):
async def test_step_discovery(hass, flow_handler, local_impl):
"""Check flow triggers from discovery."""
hass.config.api.base_url = "https://example.com"
await async_process_ha_core_config(
hass, {"external_url": "https://example.com"},
)
flow_handler.async_register_implementation(hass, local_impl)
config_entry_oauth2_flow.async_register_implementation(
hass, TEST_DOMAIN, MockOAuth2Implementation()
@ -140,7 +143,10 @@ async def test_step_discovery(hass, flow_handler, local_impl):
async def test_abort_discovered_multiple(hass, flow_handler, local_impl):
"""Test if aborts when discovered multiple times."""
hass.config.api.base_url = "https://example.com"
await async_process_ha_core_config(
hass, {"external_url": "https://example.com"},
)
flow_handler.async_register_implementation(hass, local_impl)
config_entry_oauth2_flow.async_register_implementation(
hass, TEST_DOMAIN, MockOAuth2Implementation()
@ -163,7 +169,9 @@ async def test_abort_discovered_multiple(hass, flow_handler, local_impl):
async def test_abort_discovered_existing_entries(hass, flow_handler, local_impl):
"""Test if abort discovery when entries exists."""
hass.config.api.base_url = "https://example.com"
await async_process_ha_core_config(
hass, {"external_url": "https://example.com"},
)
flow_handler.async_register_implementation(hass, local_impl)
config_entry_oauth2_flow.async_register_implementation(
hass, TEST_DOMAIN, MockOAuth2Implementation()
@ -184,7 +192,10 @@ async def test_full_flow(
hass, flow_handler, local_impl, aiohttp_client, aioclient_mock
):
"""Check full flow."""
hass.config.api.base_url = "https://example.com"
await async_process_ha_core_config(
hass, {"external_url": "https://example.com"},
)
flow_handler.async_register_implementation(hass, local_impl)
config_entry_oauth2_flow.async_register_implementation(
hass, TEST_DOMAIN, MockOAuth2Implementation()

View File

@ -119,7 +119,7 @@ async def test_get_url_internal_fallback(hass: HomeAssistant):
assert hass.config.internal_url is None
hass.config.api = Mock(
use_ssl=False, port=8123, base_url=None, local_ip="192.168.123.123"
use_ssl=False, port=8123, deprecated_base_url=None, local_ip="192.168.123.123"
)
assert _async_get_internal_url(hass) == "http://192.168.123.123:8123"
@ -133,7 +133,7 @@ async def test_get_url_internal_fallback(hass: HomeAssistant):
_async_get_internal_url(hass, require_ssl=True)
hass.config.api = Mock(
use_ssl=False, port=80, base_url=None, local_ip="192.168.123.123"
use_ssl=False, port=80, deprecated_base_url=None, local_ip="192.168.123.123"
)
assert _async_get_internal_url(hass) == "http://192.168.123.123"
assert (
@ -147,7 +147,7 @@ async def test_get_url_internal_fallback(hass: HomeAssistant):
with pytest.raises(NoURLAvailableError):
_async_get_internal_url(hass, require_ssl=True)
hass.config.api = Mock(use_ssl=True, port=443, base_url=None)
hass.config.api = Mock(use_ssl=True, port=443, deprecated_base_url=None)
with pytest.raises(NoURLAvailableError):
_async_get_internal_url(hass)
@ -161,7 +161,9 @@ async def test_get_url_internal_fallback(hass: HomeAssistant):
_async_get_internal_url(hass, require_ssl=True)
# Do no accept any local loopback address as fallback
hass.config.api = Mock(use_ssl=False, port=80, base_url=None, local_ip="127.0.0.1")
hass.config.api = Mock(
use_ssl=False, port=80, deprecated_base_url=None, local_ip="127.0.0.1"
)
with pytest.raises(NoURLAvailableError):
_async_get_internal_url(hass)
@ -367,7 +369,7 @@ async def test_get_url(hass: HomeAssistant):
async_get_url(hass)
hass.config.api = Mock(
use_ssl=False, port=8123, base_url=None, local_ip="192.168.123.123"
use_ssl=False, port=8123, deprecated_base_url=None, local_ip="192.168.123.123"
)
assert async_get_url(hass) == "http://192.168.123.123:8123"
assert async_get_url(hass, prefer_external=True) == "http://192.168.123.123:8123"
@ -409,7 +411,7 @@ async def test_get_url(hass: HomeAssistant):
async def test_get_deprecated_base_url_internal(hass: HomeAssistant):
"""Test getting an internal instance URL from the deprecated base_url."""
# Test with SSL local URL
hass.config.api = Mock(base_url="https://example.local")
hass.config.api = Mock(deprecated_base_url="https://example.local")
assert (
_async_get_deprecated_base_url(hass, internal=True) == "https://example.local"
)
@ -427,7 +429,7 @@ async def test_get_deprecated_base_url_internal(hass: HomeAssistant):
)
# Test with no SSL, local IP URL
hass.config.api = Mock(base_url="http://10.10.10.10:8123")
hass.config.api = Mock(deprecated_base_url="http://10.10.10.10:8123")
assert (
_async_get_deprecated_base_url(hass, internal=True) == "http://10.10.10.10:8123"
)
@ -442,7 +444,7 @@ async def test_get_deprecated_base_url_internal(hass: HomeAssistant):
_async_get_deprecated_base_url(hass, internal=True, require_standard_port=True)
# Test with SSL, local IP URL
hass.config.api = Mock(base_url="https://10.10.10.10")
hass.config.api = Mock(deprecated_base_url="https://10.10.10.10")
assert _async_get_deprecated_base_url(hass, internal=True) == "https://10.10.10.10"
assert (
_async_get_deprecated_base_url(hass, internal=True, require_ssl=True)
@ -454,7 +456,7 @@ async def test_get_deprecated_base_url_internal(hass: HomeAssistant):
)
# Test external URL
hass.config.api = Mock(base_url="https://example.com")
hass.config.api = Mock(deprecated_base_url="https://example.com")
with pytest.raises(NoURLAvailableError):
_async_get_deprecated_base_url(hass, internal=True)
@ -468,7 +470,7 @@ async def test_get_deprecated_base_url_internal(hass: HomeAssistant):
_async_get_deprecated_base_url(hass, internal=True, allow_ip=False)
# Test with loopback
hass.config.api = Mock(base_url="https://127.0.0.42")
hass.config.api = Mock(deprecated_base_url="https://127.0.0.42")
with pytest.raises(NoURLAvailableError):
assert _async_get_deprecated_base_url(hass, internal=True)
@ -485,7 +487,7 @@ async def test_get_deprecated_base_url_internal(hass: HomeAssistant):
async def test_get_deprecated_base_url_external(hass: HomeAssistant):
"""Test getting an external instance URL from the deprecated base_url."""
# Test with SSL and external domain on standard port
hass.config.api = Mock(base_url="https://example.com:443/")
hass.config.api = Mock(deprecated_base_url="https://example.com:443/")
assert _async_get_deprecated_base_url(hass) == "https://example.com"
assert (
_async_get_deprecated_base_url(hass, require_ssl=True) == "https://example.com"
@ -496,7 +498,7 @@ async def test_get_deprecated_base_url_external(hass: HomeAssistant):
)
# Test without SSL and external domain on non-standard port
hass.config.api = Mock(base_url="http://example.com:8123/")
hass.config.api = Mock(deprecated_base_url="http://example.com:8123/")
assert _async_get_deprecated_base_url(hass) == "http://example.com:8123"
with pytest.raises(NoURLAvailableError):
@ -506,7 +508,7 @@ async def test_get_deprecated_base_url_external(hass: HomeAssistant):
_async_get_deprecated_base_url(hass, require_standard_port=True)
# Test SSL on external IP
hass.config.api = Mock(base_url="https://1.1.1.1")
hass.config.api = Mock(deprecated_base_url="https://1.1.1.1")
assert _async_get_deprecated_base_url(hass) == "https://1.1.1.1"
assert _async_get_deprecated_base_url(hass, require_ssl=True) == "https://1.1.1.1"
assert (
@ -518,7 +520,7 @@ async def test_get_deprecated_base_url_external(hass: HomeAssistant):
_async_get_deprecated_base_url(hass, allow_ip=False)
# Test with private IP
hass.config.api = Mock(base_url="https://10.10.10.10")
hass.config.api = Mock(deprecated_base_url="https://10.10.10.10")
with pytest.raises(NoURLAvailableError):
assert _async_get_deprecated_base_url(hass)
@ -532,7 +534,7 @@ async def test_get_deprecated_base_url_external(hass: HomeAssistant):
_async_get_deprecated_base_url(hass, require_standard_port=True)
# Test with local domain
hass.config.api = Mock(base_url="https://example.local")
hass.config.api = Mock(deprecated_base_url="https://example.local")
with pytest.raises(NoURLAvailableError):
assert _async_get_deprecated_base_url(hass)
@ -546,7 +548,7 @@ async def test_get_deprecated_base_url_external(hass: HomeAssistant):
_async_get_deprecated_base_url(hass, require_standard_port=True)
# Test with loopback
hass.config.api = Mock(base_url="https://127.0.0.42")
hass.config.api = Mock(deprecated_base_url="https://127.0.0.42")
with pytest.raises(NoURLAvailableError):
assert _async_get_deprecated_base_url(hass)
@ -563,7 +565,7 @@ async def test_get_deprecated_base_url_external(hass: HomeAssistant):
async def test_get_internal_url_with_base_url_fallback(hass: HomeAssistant):
"""Test getting an internal instance URL with the deprecated base_url fallback."""
hass.config.api = Mock(
use_ssl=False, port=8123, base_url=None, local_ip="192.168.123.123"
use_ssl=False, port=8123, deprecated_base_url=None, local_ip="192.168.123.123"
)
assert hass.config.internal_url is None
assert _async_get_internal_url(hass) == "http://192.168.123.123:8123"
@ -578,7 +580,9 @@ async def test_get_internal_url_with_base_url_fallback(hass: HomeAssistant):
_async_get_internal_url(hass, require_ssl=True)
# Add base_url
hass.config.api = Mock(use_ssl=False, port=8123, base_url="https://example.local")
hass.config.api = Mock(
use_ssl=False, port=8123, deprecated_base_url="https://example.local"
)
assert _async_get_internal_url(hass) == "https://example.local"
assert _async_get_internal_url(hass, allow_ip=False) == "https://example.local"
assert (
@ -626,14 +630,14 @@ async def test_get_internal_url_with_base_url_fallback(hass: HomeAssistant):
async def test_get_external_url_with_base_url_fallback(hass: HomeAssistant):
"""Test getting an external instance URL with the deprecated base_url fallback."""
hass.config.api = Mock(use_ssl=False, port=8123, base_url=None)
hass.config.api = Mock(use_ssl=False, port=8123, deprecated_base_url=None)
assert hass.config.internal_url is None
with pytest.raises(NoURLAvailableError):
_async_get_external_url(hass)
# Test with SSL and external domain on standard port
hass.config.api = Mock(base_url="https://example.com:443/")
hass.config.api = Mock(deprecated_base_url="https://example.com:443/")
assert _async_get_external_url(hass) == "https://example.com"
assert _async_get_external_url(hass, allow_ip=False) == "https://example.com"
assert _async_get_external_url(hass, require_ssl=True) == "https://example.com"

View File

@ -1310,12 +1310,12 @@ async def test_migration_base_url(hass, hass_storage):
assert mock_listen.mock_calls[0][1][0] == EVENT_HOMEASSISTANT_START
# External
hass.config.api = Mock(base_url="https://loaded-example.com")
hass.config.api = Mock(deprecated_base_url="https://loaded-example.com")
await mock_listen.mock_calls[0][1][1](None)
assert config.external_url == "https://loaded-example.com"
# Internal
for internal in ("http://hass.local", "http://192.168.1.100:8123"):
hass.config.api = Mock(base_url=internal)
hass.config.api = Mock(deprecated_base_url=internal)
await mock_listen.mock_calls[0][1][1](None)
assert config.internal_url == internal