Add state check to config entry setup to ensure it cannot be setup twice (#117193)
This commit is contained in:
parent
c21dac855a
commit
c74c2f3652
3 changed files with 56 additions and 7 deletions
|
@ -517,6 +517,15 @@ class ConfigEntry(Generic[_DataT]):
|
||||||
|
|
||||||
# Only store setup result as state if it was not forwarded.
|
# Only store setup result as state if it was not forwarded.
|
||||||
if domain_is_integration := self.domain == integration.domain:
|
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)
|
self._async_set_state(hass, ConfigEntryState.SETUP_IN_PROGRESS, None)
|
||||||
|
|
||||||
if self.supports_unload is 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,
|
CONFIG_ENTRY_MAC_ADDRESS: TEST_MAC_ADDRESS,
|
||||||
},
|
},
|
||||||
source=config_entries.SOURCE_SSDP,
|
source=config_entries.SOURCE_SSDP,
|
||||||
state=config_entries.ConfigEntryState.LOADED,
|
state=config_entries.ConfigEntryState.NOT_LOADED,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
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,
|
CONFIG_ENTRY_HOST: TEST_HOST,
|
||||||
},
|
},
|
||||||
source=config_entries.SOURCE_SSDP,
|
source=config_entries.SOURCE_SSDP,
|
||||||
state=config_entries.ConfigEntryState.LOADED,
|
state=config_entries.ConfigEntryState.NOT_LOADED,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
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,
|
CONFIG_ENTRY_MAC_ADDRESS: TEST_MAC_ADDRESS,
|
||||||
},
|
},
|
||||||
source=config_entries.SOURCE_SSDP,
|
source=config_entries.SOURCE_SSDP,
|
||||||
state=config_entries.ConfigEntryState.LOADED,
|
state=config_entries.ConfigEntryState.NOT_LOADED,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
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,
|
CONFIG_ENTRY_MAC_ADDRESS: TEST_MAC_ADDRESS,
|
||||||
},
|
},
|
||||||
source=config_entries.SOURCE_SSDP,
|
source=config_entries.SOURCE_SSDP,
|
||||||
state=config_entries.ConfigEntryState.LOADED,
|
state=config_entries.ConfigEntryState.NOT_LOADED,
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
|
|
@ -386,7 +386,7 @@ async def test_remove_entry(
|
||||||
]
|
]
|
||||||
|
|
||||||
# Setup entry
|
# Setup entry
|
||||||
await entry.async_setup(hass)
|
await manager.async_setup(entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
# Check entity state got added
|
# Check entity state got added
|
||||||
|
@ -1613,7 +1613,9 @@ async def test_entry_reload_succeed(
|
||||||
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test that we can reload an entry."""
|
"""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)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
async_setup = AsyncMock(return_value=True)
|
async_setup = AsyncMock(return_value=True)
|
||||||
|
@ -1637,6 +1639,42 @@ async def test_entry_reload_succeed(
|
||||||
assert entry.state is config_entries.ConfigEntryState.LOADED
|
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(
|
@pytest.mark.parametrize(
|
||||||
"state",
|
"state",
|
||||||
[
|
[
|
||||||
|
@ -4005,7 +4043,9 @@ async def test_entry_reload_concurrency_not_setup_setup(
|
||||||
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
hass: HomeAssistant, manager: config_entries.ConfigEntries
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test multiple reload calls do not cause a reload race."""
|
"""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)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
async_setup = AsyncMock(return_value=True)
|
async_setup = AsyncMock(return_value=True)
|
||||||
|
|
Loading…
Add table
Reference in a new issue