Add state check to config entry setup to ensure it cannot be setup twice (#117193)
parent
8128449879
commit
750ec261be
|
@ -514,6 +514,15 @@ class ConfigEntry:
|
|||
|
||||
# Only store setup result as state if it was not forwarded.
|
||||
if domain_is_integration := self.domain == integration.domain:
|
||||
if self.state in (
|
||||
ConfigEntryState.LOADED,
|
||||
ConfigEntryState.SETUP_IN_PROGRESS,
|
||||
):
|
||||
raise OperationNotAllowed(
|
||||
f"The config entry {self.title} ({self.domain}) with entry_id"
|
||||
f" {self.entry_id} cannot be setup because is already loaded in the"
|
||||
f" {self.state} state"
|
||||
)
|
||||
self._async_set_state(hass, ConfigEntryState.SETUP_IN_PROGRESS, None)
|
||||
|
||||
if self.supports_unload is None:
|
||||
|
|
|
@ -196,7 +196,7 @@ async def test_flow_ssdp_discovery_changed_udn_match_mac(hass: HomeAssistant) ->
|
|||
CONFIG_ENTRY_MAC_ADDRESS: TEST_MAC_ADDRESS,
|
||||
},
|
||||
source=config_entries.SOURCE_SSDP,
|
||||
state=config_entries.ConfigEntryState.LOADED,
|
||||
state=config_entries.ConfigEntryState.NOT_LOADED,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
|
@ -228,7 +228,7 @@ async def test_flow_ssdp_discovery_changed_udn_match_host(hass: HomeAssistant) -
|
|||
CONFIG_ENTRY_HOST: TEST_HOST,
|
||||
},
|
||||
source=config_entries.SOURCE_SSDP,
|
||||
state=config_entries.ConfigEntryState.LOADED,
|
||||
state=config_entries.ConfigEntryState.NOT_LOADED,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
|
@ -266,7 +266,7 @@ async def test_flow_ssdp_discovery_changed_udn_but_st_differs(
|
|||
CONFIG_ENTRY_MAC_ADDRESS: TEST_MAC_ADDRESS,
|
||||
},
|
||||
source=config_entries.SOURCE_SSDP,
|
||||
state=config_entries.ConfigEntryState.LOADED,
|
||||
state=config_entries.ConfigEntryState.NOT_LOADED,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
|
@ -320,7 +320,7 @@ async def test_flow_ssdp_discovery_changed_location(hass: HomeAssistant) -> None
|
|||
CONFIG_ENTRY_MAC_ADDRESS: TEST_MAC_ADDRESS,
|
||||
},
|
||||
source=config_entries.SOURCE_SSDP,
|
||||
state=config_entries.ConfigEntryState.LOADED,
|
||||
state=config_entries.ConfigEntryState.NOT_LOADED,
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
|
|
|
@ -469,7 +469,7 @@ async def test_remove_entry(
|
|||
]
|
||||
|
||||
# Setup entry
|
||||
await entry.async_setup(hass)
|
||||
await manager.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Check entity state got added
|
||||
|
@ -1696,7 +1696,9 @@ async def test_entry_reload_succeed(
|
|||
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
||||
) -> None:
|
||||
"""Test that we can reload an entry."""
|
||||
entry = MockConfigEntry(domain="comp", state=config_entries.ConfigEntryState.LOADED)
|
||||
entry = MockConfigEntry(
|
||||
domain="comp", state=config_entries.ConfigEntryState.NOT_LOADED
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
async_setup = AsyncMock(return_value=True)
|
||||
|
@ -1720,6 +1722,42 @@ async def test_entry_reload_succeed(
|
|||
assert entry.state is config_entries.ConfigEntryState.LOADED
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"state",
|
||||
[
|
||||
config_entries.ConfigEntryState.LOADED,
|
||||
config_entries.ConfigEntryState.SETUP_IN_PROGRESS,
|
||||
],
|
||||
)
|
||||
async def test_entry_cannot_be_loaded_twice(
|
||||
hass: HomeAssistant, state: config_entries.ConfigEntryState
|
||||
) -> None:
|
||||
"""Test that a config entry cannot be loaded twice."""
|
||||
entry = MockConfigEntry(domain="comp", state=state)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
async_setup = AsyncMock(return_value=True)
|
||||
async_setup_entry = AsyncMock(return_value=True)
|
||||
async_unload_entry = AsyncMock(return_value=True)
|
||||
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
"comp",
|
||||
async_setup=async_setup,
|
||||
async_setup_entry=async_setup_entry,
|
||||
async_unload_entry=async_unload_entry,
|
||||
),
|
||||
)
|
||||
mock_platform(hass, "comp.config_flow", None)
|
||||
|
||||
with pytest.raises(config_entries.OperationNotAllowed, match=str(state)):
|
||||
await entry.async_setup(hass)
|
||||
assert len(async_setup.mock_calls) == 0
|
||||
assert len(async_setup_entry.mock_calls) == 0
|
||||
assert entry.state is state
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"state",
|
||||
[
|
||||
|
@ -4088,7 +4126,9 @@ async def test_entry_reload_concurrency_not_setup_setup(
|
|||
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
||||
) -> None:
|
||||
"""Test multiple reload calls do not cause a reload race."""
|
||||
entry = MockConfigEntry(domain="comp", state=config_entries.ConfigEntryState.LOADED)
|
||||
entry = MockConfigEntry(
|
||||
domain="comp", state=config_entries.ConfigEntryState.NOT_LOADED
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
async_setup = AsyncMock(return_value=True)
|
||||
|
|
Loading…
Reference in New Issue