mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 14:57:09 +00:00
Enable cert_expiry config entries (#25624)
* Enable cert_expiry config entries * add black * lint fixes * Rerun black * Black on json files is a bad idea * Work on comments * Forgot the lint * More comment work * Correctly set defaults * More comments * Add codeowner * Fix black * More comments implemented * Removed the catch * Add helper.py from cert_expiry to .coveragerc
This commit is contained in:
parent
49ad527a37
commit
33bd9c83fb
@ -93,6 +93,7 @@ omit =
|
|||||||
homeassistant/components/canary/camera.py
|
homeassistant/components/canary/camera.py
|
||||||
homeassistant/components/cast/*
|
homeassistant/components/cast/*
|
||||||
homeassistant/components/cert_expiry/sensor.py
|
homeassistant/components/cert_expiry/sensor.py
|
||||||
|
homeassistant/components/cert_expiry/helper.py
|
||||||
homeassistant/components/channels/media_player.py
|
homeassistant/components/channels/media_player.py
|
||||||
homeassistant/components/cisco_ios/device_tracker.py
|
homeassistant/components/cisco_ios/device_tracker.py
|
||||||
homeassistant/components/cisco_mobility_express/device_tracker.py
|
homeassistant/components/cisco_mobility_express/device_tracker.py
|
||||||
|
@ -46,6 +46,7 @@ homeassistant/components/broadlink/* @danielhiversen
|
|||||||
homeassistant/components/brunt/* @eavanvalkenburg
|
homeassistant/components/brunt/* @eavanvalkenburg
|
||||||
homeassistant/components/bt_smarthub/* @jxwolstenholme
|
homeassistant/components/bt_smarthub/* @jxwolstenholme
|
||||||
homeassistant/components/buienradar/* @mjj4791 @ties
|
homeassistant/components/buienradar/* @mjj4791 @ties
|
||||||
|
homeassistant/components/cert_expiry/* @cereal2nd
|
||||||
homeassistant/components/cisco_ios/* @fbradyirl
|
homeassistant/components/cisco_ios/* @fbradyirl
|
||||||
homeassistant/components/cisco_mobility_express/* @fbradyirl
|
homeassistant/components/cisco_mobility_express/* @fbradyirl
|
||||||
homeassistant/components/cisco_webex_teams/* @fbradyirl
|
homeassistant/components/cisco_webex_teams/* @fbradyirl
|
||||||
|
24
homeassistant/components/cert_expiry/.translations/en.json
Normal file
24
homeassistant/components/cert_expiry/.translations/en.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"host_port_exists": "This host and port combination is already configured"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"certificate_fetch_failed": "Can not fetch certificate from this host and port combination",
|
||||||
|
"connection_timeout": "Timeout whemn connecting to this host",
|
||||||
|
"host_port_exists": "This host and port combination is already configured",
|
||||||
|
"resolve_failed": "This host can not be resolved"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"host": "The hostname of the certificate",
|
||||||
|
"name": "The name of the certificate",
|
||||||
|
"port": "The port of the certificate"
|
||||||
|
},
|
||||||
|
"title": "Define the certificate to test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "Certificate Expiry"
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,25 @@
|
|||||||
"""The cert_expiry component."""
|
"""The cert_expiry component."""
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
||||||
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup(hass, config):
|
||||||
|
"""Platform setup, do nothing."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry):
|
||||||
|
"""Load the saved entities."""
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_start(_):
|
||||||
|
"""Load the entry after the start event."""
|
||||||
|
hass.async_create_task(
|
||||||
|
hass.config_entries.async_forward_entry_setup(entry, "sensor")
|
||||||
|
)
|
||||||
|
|
||||||
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, async_start)
|
||||||
|
|
||||||
|
return True
|
||||||
|
98
homeassistant/components/cert_expiry/config_flow.py
Normal file
98
homeassistant/components/cert_expiry/config_flow.py
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
"""Config flow for the Cert Expiry platform."""
|
||||||
|
import socket
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.const import CONF_PORT, CONF_NAME, CONF_HOST
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.util import slugify
|
||||||
|
|
||||||
|
from .const import DOMAIN, DEFAULT_PORT, DEFAULT_NAME
|
||||||
|
from .helper import get_cert
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def certexpiry_entries(hass: HomeAssistant):
|
||||||
|
"""Return the host,port tuples for the domain."""
|
||||||
|
return set(
|
||||||
|
(entry.data[CONF_HOST], entry.data[CONF_PORT])
|
||||||
|
for entry in hass.config_entries.async_entries(DOMAIN)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CertexpiryConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
|
"""Handle a config flow."""
|
||||||
|
|
||||||
|
VERSION = 1
|
||||||
|
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
"""Initialize the config flow."""
|
||||||
|
self._errors = {}
|
||||||
|
|
||||||
|
def _prt_in_configuration_exists(self, user_input) -> bool:
|
||||||
|
"""Return True if host, port combination exists in configuration."""
|
||||||
|
host = user_input[CONF_HOST]
|
||||||
|
port = user_input.get(CONF_PORT, DEFAULT_PORT)
|
||||||
|
if (host, port) in certexpiry_entries(self.hass):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _test_connection(self, user_input=None):
|
||||||
|
"""Test connection to the server and try to get the certtificate."""
|
||||||
|
try:
|
||||||
|
get_cert(user_input[CONF_HOST], user_input.get(CONF_PORT, DEFAULT_PORT))
|
||||||
|
return True
|
||||||
|
except socket.gaierror:
|
||||||
|
self._errors[CONF_HOST] = "resolve_failed"
|
||||||
|
except socket.timeout:
|
||||||
|
self._errors[CONF_HOST] = "connection_timeout"
|
||||||
|
except OSError:
|
||||||
|
self._errors[CONF_HOST] = "certificate_fetch_failed"
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def async_step_user(self, user_input=None):
|
||||||
|
"""Step when user intializes a integration."""
|
||||||
|
self._errors = {}
|
||||||
|
if user_input is not None:
|
||||||
|
# set some defaults in case we need to return to the form
|
||||||
|
if self._prt_in_configuration_exists(user_input):
|
||||||
|
self._errors[CONF_HOST] = "host_port_exists"
|
||||||
|
else:
|
||||||
|
if self._test_connection(user_input):
|
||||||
|
host = user_input[CONF_HOST]
|
||||||
|
name = slugify(user_input.get(CONF_NAME, DEFAULT_NAME))
|
||||||
|
prt = user_input.get(CONF_PORT, DEFAULT_PORT)
|
||||||
|
return self.async_create_entry(
|
||||||
|
title=name, data={CONF_HOST: host, CONF_PORT: prt}
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
user_input = {}
|
||||||
|
user_input[CONF_NAME] = DEFAULT_NAME
|
||||||
|
user_input[CONF_HOST] = ""
|
||||||
|
user_input[CONF_PORT] = DEFAULT_PORT
|
||||||
|
|
||||||
|
return self.async_show_form(
|
||||||
|
step_id="user",
|
||||||
|
data_schema=vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Required(
|
||||||
|
CONF_NAME, default=user_input.get(CONF_NAME, DEFAULT_NAME)
|
||||||
|
): str,
|
||||||
|
vol.Required(CONF_HOST, default=user_input[CONF_HOST]): str,
|
||||||
|
vol.Required(
|
||||||
|
CONF_PORT, default=user_input.get(CONF_PORT, DEFAULT_PORT)
|
||||||
|
): int,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
errors=self._errors,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def async_step_import(self, user_input=None):
|
||||||
|
"""Import a config entry.
|
||||||
|
|
||||||
|
Only host was required in the yaml file all other fields are optional
|
||||||
|
"""
|
||||||
|
if self._prt_in_configuration_exists(user_input):
|
||||||
|
return self.async_abort(reason="host_port_exists")
|
||||||
|
return await self.async_step_user(user_input)
|
6
homeassistant/components/cert_expiry/const.py
Normal file
6
homeassistant/components/cert_expiry/const.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
"""Const for Cert Expiry."""
|
||||||
|
|
||||||
|
DOMAIN = "cert_expiry"
|
||||||
|
DEFAULT_NAME = "SSL Certificate Expiry"
|
||||||
|
DEFAULT_PORT = 443
|
||||||
|
TIMEOUT = 10.0
|
15
homeassistant/components/cert_expiry/helper.py
Normal file
15
homeassistant/components/cert_expiry/helper.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
"""Helper functions for the Cert Expiry platform."""
|
||||||
|
import socket
|
||||||
|
import ssl
|
||||||
|
|
||||||
|
from .const import TIMEOUT
|
||||||
|
|
||||||
|
|
||||||
|
def get_cert(host, port):
|
||||||
|
"""Get the ssl certificate for the host and port combination."""
|
||||||
|
ctx = ssl.create_default_context()
|
||||||
|
address = (host, port)
|
||||||
|
with socket.create_connection(address, timeout=TIMEOUT) as sock:
|
||||||
|
with ctx.wrap_socket(sock, server_hostname=address[0]) as ssock:
|
||||||
|
cert = ssock.getpeercert()
|
||||||
|
return cert
|
@ -3,6 +3,7 @@
|
|||||||
"name": "Cert expiry",
|
"name": "Cert expiry",
|
||||||
"documentation": "https://www.home-assistant.io/components/cert_expiry",
|
"documentation": "https://www.home-assistant.io/components/cert_expiry",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
|
"config_flow": true,
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": []
|
"codeowners": ["@cereal2nd"]
|
||||||
}
|
}
|
||||||
|
@ -7,24 +7,18 @@ from datetime import datetime, timedelta
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.config_entries import SOURCE_IMPORT
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||||
from homeassistant.const import (
|
from homeassistant.const import CONF_NAME, CONF_HOST, CONF_PORT
|
||||||
CONF_NAME,
|
|
||||||
CONF_HOST,
|
|
||||||
CONF_PORT,
|
|
||||||
EVENT_HOMEASSISTANT_START,
|
|
||||||
)
|
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
|
from .const import DOMAIN, DEFAULT_NAME, DEFAULT_PORT
|
||||||
|
from .helper import get_cert
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_NAME = "SSL Certificate Expiry"
|
|
||||||
DEFAULT_PORT = 443
|
|
||||||
|
|
||||||
SCAN_INTERVAL = timedelta(hours=12)
|
SCAN_INTERVAL = timedelta(hours=12)
|
||||||
|
|
||||||
TIMEOUT = 10.0
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_HOST): cv.string,
|
vol.Required(CONF_HOST): cv.string,
|
||||||
@ -34,22 +28,22 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||||
"""Set up certificate expiry sensor."""
|
"""Set up certificate expiry sensor."""
|
||||||
|
hass.async_create_task(
|
||||||
|
hass.config_entries.flow.async_init(
|
||||||
|
DOMAIN, context={"source": SOURCE_IMPORT}, data=dict(config)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def run_setup(event):
|
|
||||||
"""Wait until Home Assistant is fully initialized before creating.
|
|
||||||
|
|
||||||
Delay the setup until Home Assistant is fully initialized.
|
async def async_setup_entry(hass, entry, async_add_entities):
|
||||||
"""
|
"""Add cert-expiry entry."""
|
||||||
server_name = config.get(CONF_HOST)
|
async_add_entities(
|
||||||
server_port = config.get(CONF_PORT)
|
[SSLCertificate(entry.title, entry.data[CONF_HOST], entry.data[CONF_PORT])],
|
||||||
sensor_name = config.get(CONF_NAME)
|
True,
|
||||||
|
)
|
||||||
add_entities([SSLCertificate(sensor_name, server_name, server_port)], True)
|
return True
|
||||||
|
|
||||||
# To allow checking of the HA certificate we must first be running.
|
|
||||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, run_setup)
|
|
||||||
|
|
||||||
|
|
||||||
class SSLCertificate(Entity):
|
class SSLCertificate(Entity):
|
||||||
@ -90,13 +84,8 @@ class SSLCertificate(Entity):
|
|||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Fetch the certificate information."""
|
"""Fetch the certificate information."""
|
||||||
ctx = ssl.create_default_context()
|
|
||||||
try:
|
try:
|
||||||
address = (self.server_name, self.server_port)
|
cert = get_cert(self.server_name, self.server_port)
|
||||||
with socket.create_connection(address, timeout=TIMEOUT) as sock:
|
|
||||||
with ctx.wrap_socket(sock, server_hostname=address[0]) as ssock:
|
|
||||||
cert = ssock.getpeercert()
|
|
||||||
|
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
_LOGGER.error("Cannot resolve hostname: %s", self.server_name)
|
_LOGGER.error("Cannot resolve hostname: %s", self.server_name)
|
||||||
self._available = False
|
self._available = False
|
||||||
|
24
homeassistant/components/cert_expiry/strings.json
Normal file
24
homeassistant/components/cert_expiry/strings.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"title": "Certificate Expiry",
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"title": "Define the certificate to test",
|
||||||
|
"data": {
|
||||||
|
"name": "The name of the certificate",
|
||||||
|
"host": "The hostname of the certificate",
|
||||||
|
"port": "The port of the certificate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"host_port_exists": "This host and port combination is already configured",
|
||||||
|
"resolve_failed": "This host can not be resolved",
|
||||||
|
"connection_timeout": "Timeout whemn connecting to this host",
|
||||||
|
"certificate_fetch_failed": "Can not fetch certificate from this host and port combination"
|
||||||
|
},
|
||||||
|
"abort": {
|
||||||
|
"host_port_exists": "This host and port combination is already configured"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ FLOWS = [
|
|||||||
"ambient_station",
|
"ambient_station",
|
||||||
"axis",
|
"axis",
|
||||||
"cast",
|
"cast",
|
||||||
|
"cert_expiry",
|
||||||
"daikin",
|
"daikin",
|
||||||
"deconz",
|
"deconz",
|
||||||
"dialogflow",
|
"dialogflow",
|
||||||
|
1
tests/components/cert_expiry/__init__.py
Normal file
1
tests/components/cert_expiry/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Tests for the Cert Expiry component."""
|
137
tests/components/cert_expiry/test_config_flow.py
Normal file
137
tests/components/cert_expiry/test_config_flow.py
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
"""Tests for the Cert Expiry config flow."""
|
||||||
|
import pytest
|
||||||
|
import socket
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from homeassistant import data_entry_flow
|
||||||
|
from homeassistant.components.cert_expiry import config_flow
|
||||||
|
from homeassistant.components.cert_expiry.const import DEFAULT_PORT
|
||||||
|
from homeassistant.const import CONF_PORT, CONF_NAME, CONF_HOST
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
NAME = "Cert Expiry test 1 2 3"
|
||||||
|
PORT = 443
|
||||||
|
HOST = "example.com"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="test_connect")
|
||||||
|
def mock_controller():
|
||||||
|
"""Mock a successfull _prt_in_configuration_exists."""
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.cert_expiry.config_flow.CertexpiryConfigFlow._test_connection",
|
||||||
|
return_value=True,
|
||||||
|
):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
def init_config_flow(hass):
|
||||||
|
"""Init a configuration flow."""
|
||||||
|
flow = config_flow.CertexpiryConfigFlow()
|
||||||
|
flow.hass = hass
|
||||||
|
return flow
|
||||||
|
|
||||||
|
|
||||||
|
async def test_user(hass, test_connect):
|
||||||
|
"""Test user config."""
|
||||||
|
flow = init_config_flow(hass)
|
||||||
|
|
||||||
|
result = await flow.async_step_user()
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "user"
|
||||||
|
|
||||||
|
# tets with all provided
|
||||||
|
result = await flow.async_step_user(
|
||||||
|
{CONF_NAME: NAME, CONF_HOST: HOST, CONF_PORT: PORT}
|
||||||
|
)
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result["title"] == "cert_expiry_test_1_2_3"
|
||||||
|
assert result["data"][CONF_HOST] == HOST
|
||||||
|
assert result["data"][CONF_PORT] == PORT
|
||||||
|
|
||||||
|
|
||||||
|
async def test_import(hass, test_connect):
|
||||||
|
"""Test import step."""
|
||||||
|
flow = init_config_flow(hass)
|
||||||
|
|
||||||
|
# import with only host
|
||||||
|
result = await flow.async_step_import({CONF_HOST: HOST})
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result["title"] == "ssl_certificate_expiry"
|
||||||
|
assert result["data"][CONF_HOST] == HOST
|
||||||
|
assert result["data"][CONF_PORT] == DEFAULT_PORT
|
||||||
|
|
||||||
|
# import with host and name
|
||||||
|
result = await flow.async_step_import({CONF_HOST: HOST, CONF_NAME: NAME})
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result["title"] == "cert_expiry_test_1_2_3"
|
||||||
|
assert result["data"][CONF_HOST] == HOST
|
||||||
|
assert result["data"][CONF_PORT] == DEFAULT_PORT
|
||||||
|
|
||||||
|
# improt with host and port
|
||||||
|
result = await flow.async_step_import({CONF_HOST: HOST, CONF_PORT: PORT})
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result["title"] == "ssl_certificate_expiry"
|
||||||
|
assert result["data"][CONF_HOST] == HOST
|
||||||
|
assert result["data"][CONF_PORT] == PORT
|
||||||
|
|
||||||
|
# import with all
|
||||||
|
result = await flow.async_step_import(
|
||||||
|
{CONF_HOST: HOST, CONF_PORT: PORT, CONF_NAME: NAME}
|
||||||
|
)
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result["title"] == "cert_expiry_test_1_2_3"
|
||||||
|
assert result["data"][CONF_HOST] == HOST
|
||||||
|
assert result["data"][CONF_PORT] == PORT
|
||||||
|
|
||||||
|
|
||||||
|
async def test_abort_if_already_setup(hass, test_connect):
|
||||||
|
"""Test we abort if the cert is already setup."""
|
||||||
|
flow = init_config_flow(hass)
|
||||||
|
MockConfigEntry(
|
||||||
|
domain="cert_expiry",
|
||||||
|
data={CONF_PORT: DEFAULT_PORT, CONF_NAME: NAME, CONF_HOST: HOST},
|
||||||
|
).add_to_hass(hass)
|
||||||
|
|
||||||
|
# Should fail, same HOST and PORT (default)
|
||||||
|
result = await flow.async_step_import(
|
||||||
|
{CONF_HOST: HOST, CONF_NAME: NAME, CONF_PORT: DEFAULT_PORT}
|
||||||
|
)
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||||
|
assert result["reason"] == "host_port_exists"
|
||||||
|
|
||||||
|
# Should be the same HOST and PORT (default)
|
||||||
|
result = await flow.async_step_user(
|
||||||
|
{CONF_HOST: HOST, CONF_NAME: NAME, CONF_PORT: DEFAULT_PORT}
|
||||||
|
)
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["errors"] == {CONF_HOST: "host_port_exists"}
|
||||||
|
|
||||||
|
# SHOULD pass, same Host diff PORT
|
||||||
|
result = await flow.async_step_import(
|
||||||
|
{CONF_HOST: HOST, CONF_NAME: NAME, CONF_PORT: 888}
|
||||||
|
)
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
|
assert result["title"] == "cert_expiry_test_1_2_3"
|
||||||
|
assert result["data"][CONF_HOST] == HOST
|
||||||
|
assert result["data"][CONF_PORT] == 888
|
||||||
|
|
||||||
|
|
||||||
|
async def test_abort_on_socket_failed(hass):
|
||||||
|
"""Test we abort of we have errors during socket creation."""
|
||||||
|
flow = init_config_flow(hass)
|
||||||
|
|
||||||
|
with patch("socket.create_connection", side_effect=socket.gaierror()):
|
||||||
|
result = await flow.async_step_user({CONF_HOST: HOST})
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["errors"] == {CONF_HOST: "resolve_failed"}
|
||||||
|
|
||||||
|
with patch("socket.create_connection", side_effect=socket.timeout()):
|
||||||
|
result = await flow.async_step_user({CONF_HOST: HOST})
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["errors"] == {CONF_HOST: "connection_timeout"}
|
||||||
|
|
||||||
|
with patch("socket.create_connection", side_effect=OSError()):
|
||||||
|
result = await flow.async_step_user({CONF_HOST: HOST})
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["errors"] == {CONF_HOST: "certificate_fetch_failed"}
|
Loading…
x
Reference in New Issue
Block a user