allow overriding host api url in config flow (#33481)

* allow overriding host api url in config flow

* fix typo

* capitalize URL
pull/33488/head
Kit Klein 2020-03-31 18:50:37 -04:00 committed by GitHub
parent b892dbc6ea
commit 955c94e313
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 91 additions and 20 deletions

View File

@ -33,6 +33,9 @@
"abort": {
"not_konn_panel": "Not a recognized Konnected.io device"
},
"error": {
"bad_host": "Invalid Override API host url"
},
"step": {
"options_binary": {
"data": {
@ -82,7 +85,9 @@
},
"options_misc": {
"data": {
"blink": "Blink panel LED on when sending state change"
"api_host": "Override API host URL (optional)",
"blink": "Blink panel LED on when sending state change",
"override_api_host": "Override default Home Assistant API host panel URL"
},
"description": "Please select the desired behavior for your panel",
"title": "Configure Misc"

View File

@ -91,7 +91,7 @@ def ensure_zone(value):
return str(value)
def import_validator(config):
def import_device_validator(config):
"""Validate zones and reformat for import."""
config = copy.deepcopy(config)
io_cfgs = {}
@ -117,10 +117,22 @@ def import_validator(config):
config.pop(CONF_SWITCHES, None)
config.pop(CONF_BLINK, None)
config.pop(CONF_DISCOVERY, None)
config.pop(CONF_API_HOST, None)
config.pop(CONF_IO, None)
return config
def import_validator(config):
"""Reformat for import."""
config = copy.deepcopy(config)
# push api_host into device configs
for device in config.get(CONF_DEVICES, []):
device[CONF_API_HOST] = config.get(CONF_API_HOST, "")
return config
# configuration.yaml schemas (legacy)
BINARY_SENSOR_SCHEMA_YAML = vol.All(
vol.Schema(
@ -179,23 +191,27 @@ DEVICE_SCHEMA_YAML = vol.All(
vol.Inclusive(CONF_HOST, "host_info"): cv.string,
vol.Inclusive(CONF_PORT, "host_info"): cv.port,
vol.Optional(CONF_BLINK, default=True): cv.boolean,
vol.Optional(CONF_API_HOST, default=""): vol.Any("", cv.url),
vol.Optional(CONF_DISCOVERY, default=True): cv.boolean,
}
),
import_validator,
import_device_validator,
)
# pylint: disable=no-value-for-parameter
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Required(CONF_ACCESS_TOKEN): cv.string,
vol.Optional(CONF_API_HOST): vol.Url(),
vol.Optional(CONF_DEVICES): vol.All(
cv.ensure_list, [DEVICE_SCHEMA_YAML]
),
}
DOMAIN: vol.All(
import_validator,
vol.Schema(
{
vol.Required(CONF_ACCESS_TOKEN): cv.string,
vol.Optional(CONF_API_HOST): vol.Url(),
vol.Optional(CONF_DEVICES): vol.All(
cv.ensure_list, [DEVICE_SCHEMA_YAML]
),
}
),
)
},
extra=vol.ALLOW_EXTRA,

View File

@ -31,6 +31,7 @@ from homeassistant.helpers import config_validation as cv
from .const import (
CONF_ACTIVATION,
CONF_API_HOST,
CONF_BLINK,
CONF_DEFAULT_OPTIONS,
CONF_DISCOVERY,
@ -61,6 +62,8 @@ CONF_MORE_STATES = "more_states"
CONF_YES = "Yes"
CONF_NO = "No"
CONF_OVERRIDE_API_HOST = "override_api_host"
KONN_MANUFACTURER = "konnected.io"
KONN_PANEL_MODEL_NAMES = {
KONN_MODEL: "Konnected Alarm Panel",
@ -138,6 +141,7 @@ OPTIONS_SCHEMA = vol.Schema(
vol.Optional(CONF_SENSORS): vol.All(cv.ensure_list, [SENSOR_SCHEMA]),
vol.Optional(CONF_SWITCHES): vol.All(cv.ensure_list, [SWITCH_SCHEMA]),
vol.Optional(CONF_BLINK, default=True): cv.boolean,
vol.Optional(CONF_API_HOST, default=""): vol.Any("", cv.url),
vol.Optional(CONF_DISCOVERY, default=True): cv.boolean,
},
extra=vol.REMOVE_EXTRA,
@ -785,8 +789,19 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
"""Allow the user to configure the LED behavior."""
errors = {}
if user_input is not None:
self.new_opt[CONF_BLINK] = user_input[CONF_BLINK]
return self.async_create_entry(title="", data=self.new_opt)
# config schema only does basic schema val so check url here
try:
if user_input[CONF_OVERRIDE_API_HOST]:
cv.url(user_input.get(CONF_API_HOST, ""))
else:
user_input[CONF_API_HOST] = ""
except vol.Invalid:
errors["base"] = "bad_host"
else:
# no need to store the override - can infer
del user_input[CONF_OVERRIDE_API_HOST]
self.new_opt.update(user_input)
return self.async_create_entry(title="", data=self.new_opt)
return self.async_show_form(
step_id="options_misc",
@ -795,6 +810,13 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
vol.Required(
CONF_BLINK, default=self.current_opt.get(CONF_BLINK, True)
): bool,
vol.Required(
CONF_OVERRIDE_API_HOST,
default=bool(self.current_opt.get(CONF_API_HOST)),
): bool,
vol.Optional(
CONF_API_HOST, default=self.current_opt.get(CONF_API_HOST, "")
): str,
}
),
errors=errors,

View File

@ -294,7 +294,9 @@ class AlarmPanel:
@callback
def async_desired_settings_payload(self):
"""Return a dict representing the desired device configuration."""
desired_api_host = (
# keeping self.hass.data check for backwards compatibility
# newly configured integrations store this in the config entry
desired_api_host = self.options.get(CONF_API_HOST) or (
self.hass.data[DOMAIN].get(CONF_API_HOST) or self.hass.config.api.base_url
)
desired_api_endpoint = desired_api_host + ENDPOINT_ROOT

View File

@ -94,11 +94,15 @@
"title": "Configure Misc",
"description": "Please select the desired behavior for your panel",
"data": {
"blink": "Blink panel LED on when sending state change"
"blink": "Blink panel LED on when sending state change",
"override_api_host": "Override default Home Assistant API host panel URL",
"api_host": "Override API host URL (optional)"
}
}
},
"error": {},
"error": {
"bad_host": "Invalid Override API host url"
},
"abort": {
"not_konn_panel": "Not a recognized Konnected.io device"
}

View File

@ -450,6 +450,7 @@ async def test_import_existing_config(hass, mock_panel):
"alarm1": "Switchable Output",
},
"blink": True,
"api_host": "",
"discovery": True,
"binary_sensors": [
{"zone": "2", "type": "door", "inverse": False},
@ -628,6 +629,7 @@ async def test_import_pin_config(hass, mock_panel):
"out": "Switchable Output",
},
"blink": True,
"api_host": "",
"discovery": True,
"binary_sensors": [
{"zone": "1", "type": "door", "inverse": False},
@ -778,9 +780,21 @@ async def test_option_flow(hass, mock_panel):
assert result["type"] == "form"
assert result["step_id"] == "options_misc"
# make sure we enforce url format
result = await hass.config_entries.options.async_configure(
result["flow_id"], user_input={"blink": True},
result["flow_id"],
user_input={"blink": True, "override_api_host": True, "api_host": "badhosturl"},
)
assert result["type"] == "form"
assert result["step_id"] == "options_misc"
result = await hass.config_entries.options.async_configure(
result["flow_id"],
user_input={
"blink": True,
"override_api_host": True,
"api_host": "http://overridehost:1111",
},
)
assert result["type"] == "create_entry"
assert result["data"] == {
@ -792,6 +806,7 @@ async def test_option_flow(hass, mock_panel):
"out": "Switchable Output",
},
"blink": True,
"api_host": "http://overridehost:1111",
"binary_sensors": [
{"zone": "2", "type": "door", "inverse": False},
{"zone": "6", "type": "window", "name": "winder", "inverse": True},
@ -958,7 +973,7 @@ async def test_option_flow_pro(hass, mock_panel):
assert result["step_id"] == "options_misc"
result = await hass.config_entries.options.async_configure(
result["flow_id"], user_input={"blink": True},
result["flow_id"], user_input={"blink": True, "override_api_host": False},
)
assert result["type"] == "create_entry"
@ -976,6 +991,7 @@ async def test_option_flow_pro(hass, mock_panel):
"out1": "Switchable Output",
},
"blink": True,
"api_host": "",
"binary_sensors": [
{"zone": "2", "type": "door", "inverse": False},
{"zone": "6", "type": "window", "name": "winder", "inverse": True},
@ -1121,7 +1137,7 @@ async def test_option_flow_import(hass, mock_panel):
schema = result["data_schema"]({})
assert schema["blink"] is True
result = await hass.config_entries.options.async_configure(
result["flow_id"], user_input={"blink": False},
result["flow_id"], user_input={"blink": False, "override_api_host": False},
)
# verify the updated fields
@ -1129,6 +1145,7 @@ async def test_option_flow_import(hass, mock_panel):
assert result["data"] == {
"io": {"1": "Binary Sensor", "2": "Digital Sensor", "3": "Switchable Output"},
"blink": False,
"api_host": "",
"binary_sensors": [
{"zone": "1", "type": "door", "inverse": True, "name": "winder"},
],

View File

@ -43,6 +43,7 @@ async def test_config_schema(hass):
"""Test that config schema is imported properly."""
config = {
konnected.DOMAIN: {
konnected.CONF_API_HOST: "http://1.1.1.1:8888",
konnected.CONF_ACCESS_TOKEN: "abcdefgh",
konnected.CONF_DEVICES: [{konnected.CONF_ID: "aabbccddeeff"}],
}
@ -50,10 +51,12 @@ async def test_config_schema(hass):
assert konnected.CONFIG_SCHEMA(config) == {
"konnected": {
"access_token": "abcdefgh",
"api_host": "http://1.1.1.1:8888",
"devices": [
{
"default_options": {
"blink": True,
"api_host": "http://1.1.1.1:8888",
"discovery": True,
"io": {
"1": "Disabled",
@ -96,6 +99,7 @@ async def test_config_schema(hass):
{
"default_options": {
"blink": True,
"api_host": "",
"discovery": True,
"io": {
"1": "Disabled",
@ -162,6 +166,7 @@ async def test_config_schema(hass):
{
"default_options": {
"blink": True,
"api_host": "",
"discovery": True,
"io": {
"1": "Binary Sensor",