Splunk component filter support (#25071)

* Added code to support entity and domain filters in the config for splunk component, and the code to enforce the filter.

* * Moved code for posting splunk request to separate function, primarily to more easily write a test case where I can mock the point where the post would occur and validate that filtering is working correctly.
* Test cases created for full config check and to test the filtering

* Correcting static check errors/issues

* Correcting flake8 static check issue (introduced when addressing prior static check issues)

* Removing unused parameter to setup function - cleanup from reviewer request.
This commit is contained in:
Alex S 2019-07-12 15:35:23 -07:00 committed by Martin Hjelmare
parent f7aa1b026f
commit f705a1e62e
2 changed files with 85 additions and 12 deletions

View File

@ -11,10 +11,12 @@ from homeassistant.const import (
CONF_PORT, CONF_TOKEN, EVENT_STATE_CHANGED)
from homeassistant.helpers import state as state_helper
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entityfilter import FILTER_SCHEMA
from homeassistant.helpers.json import JSONEncoder
_LOGGER = logging.getLogger(__name__)
CONF_FILTER = 'filter'
DOMAIN = 'splunk'
DEFAULT_HOST = 'localhost'
@ -30,10 +32,26 @@ CONFIG_SCHEMA = vol.Schema({
vol.Optional(CONF_SSL, default=False): cv.boolean,
vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_FILTER, default={}): FILTER_SCHEMA,
}),
}, extra=vol.ALLOW_EXTRA)
def post_request(event_collector, body, headers, verify_ssl):
"""Post request to Splunk."""
try:
payload = {
"host": event_collector,
"event": body,
}
requests.post(event_collector,
data=json.dumps(payload, cls=JSONEncoder),
headers=headers, timeout=10, verify=verify_ssl)
except requests.exceptions.RequestException as error:
_LOGGER.exception("Error saving event to Splunk: %s", error)
def setup(hass, config):
"""Set up the Splunk component."""
conf = config[DOMAIN]
@ -43,6 +61,7 @@ def setup(hass, config):
use_ssl = conf.get(CONF_SSL)
verify_ssl = conf.get(CONF_VERIFY_SSL)
name = conf.get(CONF_NAME)
entity_filter = conf[CONF_FILTER]
if use_ssl:
uri_scheme = 'https://'
@ -57,7 +76,7 @@ def setup(hass, config):
"""Listen for new messages on the bus and sends them to Splunk."""
state = event.data.get('new_state')
if state is None:
if state is None or not entity_filter(state.entity_id):
return
try:
@ -76,16 +95,7 @@ def setup(hass, config):
}
]
try:
payload = {
"host": event_collector,
"event": json_body,
}
requests.post(event_collector,
data=json.dumps(payload, cls=JSONEncoder),
headers=headers, timeout=10, verify=verify_ssl)
except requests.exceptions.RequestException as error:
_LOGGER.exception("Error saving event to Splunk: %s", error)
post_request(event_collector, json_body, headers, verify_ssl)
hass.bus.listen(EVENT_STATE_CHANGED, splunk_event_listener)

View File

@ -8,8 +8,12 @@ import homeassistant.components.splunk as splunk
from homeassistant.const import STATE_ON, STATE_OFF, EVENT_STATE_CHANGED
from homeassistant.helpers import state as state_helper
import homeassistant.util.dt as dt_util
from homeassistant.core import State
from tests.common import get_test_home_assistant
from tests.common import (
get_test_home_assistant,
mock_state_change_event
)
class TestSplunk(unittest.TestCase):
@ -33,6 +37,14 @@ class TestSplunk(unittest.TestCase):
'ssl': 'False',
'verify_ssl': 'True',
'name': 'hostname',
'filter': {
'exclude_domains': [
'fake'
],
'exclude_entities': [
'fake.entity'
],
}
}
}
@ -120,3 +132,54 @@ class TestSplunk(unittest.TestCase):
headers={'Authorization': 'Splunk secret'},
timeout=10, verify=True)
self.mock_post.reset_mock()
def _setup_with_filter(self):
"""Test the setup."""
config = {
'splunk': {
'host': 'host',
'token': 'secret',
'port': 8088,
'filter': {
'exclude_domains': [
'excluded_domain'
],
'exclude_entities': [
'other_domain.excluded_entity'
]
}
}
}
setup_component(self.hass, splunk.DOMAIN, config)
@mock.patch.object(splunk, 'post_request')
def test_splunk_entityfilter(self, mock_requests):
"""Test event listener."""
self._setup_with_filter()
testdata = [
{
'entity_id': 'other_domain.other_entity',
'filter_expected': False
},
{
'entity_id': 'other_domain.excluded_entity',
'filter_expected': True
},
{
'entity_id': 'excluded_domain.other_entity',
'filter_expected': True
}
]
for test in testdata:
mock_state_change_event(self.hass, State(test['entity_id'], 'on'))
self.hass.block_till_done()
if test['filter_expected']:
assert not splunk.post_request.called
else:
assert splunk.post_request.called
splunk.post_request.reset_mock()