HttpCheck can't detect changes if only change search_pattern
http check is not detecting changes when search_pattern was changed but url keeps the same. Add unit test for modify_config Change-Id: I0762e963429ec9e5c7df0d9aef7e9ef1b9b57626
This commit is contained in:
parent
ddd6fb2312
commit
224c56bbcf
145
docs/DeveloperDocs/agent_internals.md
Normal file
145
docs/DeveloperDocs/agent_internals.md
Normal file
@ -0,0 +1,145 @@
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
**Table of Contents**
|
||||
|
||||
- [Modify_Config](#modify_config)
|
||||
- [Examples](#examples)
|
||||
- [Adding a new instance](#adding-a-new-instance)
|
||||
- [Changing the current instance](#changing-the-current-instance)
|
||||
- [License](#license)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# Modify_Config
|
||||
Modify_config is a function in "monasca_setup/main.py" (link: https://github
|
||||
.com/openstack/monasca-agent/blob/master/monasca_setup/main.py). It compares
|
||||
existing and detected configurations for each check plugin and writes out the
|
||||
plugin configurations if there are changes.
|
||||
|
||||
## Examples
|
||||
There are two examples shown here using http_check: one is to add a new
|
||||
instance, another is to detect endpoint change on existing http_check instance.
|
||||
|
||||
#### Adding a new instance
|
||||
old_config:
|
||||
|
||||
```
|
||||
{'init_config': None,
|
||||
'instances': [{'built_by': 'HttpCheck',
|
||||
'name': 'logging',
|
||||
'url': 'http://127.0.0.1:9200',
|
||||
'use_keystone': False,
|
||||
'match_pattern': '.*VERSION.*',
|
||||
'collect_response_time': True,
|
||||
'timeout': '10',
|
||||
'dimensions': {'service': 'logging'}}]
|
||||
}
|
||||
```
|
||||
|
||||
monasca-setup arguments:
|
||||
|
||||
```
|
||||
monasca-setup -d 'HttpCheck' -a 'url=http://192.168.10.6:8070 match_pattern=
|
||||
.*OK.* name=monasca dimensions=service:monitoring'
|
||||
```
|
||||
|
||||
input_config generated from monasca-setup:
|
||||
|
||||
```
|
||||
{'http_check':
|
||||
{'instances': [{'built_by': 'HttpCheck',
|
||||
'name': 'monasca',
|
||||
'url': 'http://192.168.10.6:8070',
|
||||
'use_keystone': False,
|
||||
'match_pattern': '.*OK.*',
|
||||
'collect_response_time': True,
|
||||
'timeout': '10',
|
||||
'dimensions': {'service': 'monitoring'}
|
||||
}]
|
||||
'init_config': None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
output_config from modify_config:
|
||||
|
||||
```
|
||||
{'init_config': None,
|
||||
'instances': [{'built_by': 'HttpCheck',
|
||||
'name': 'logging',
|
||||
'url': 'http://127.0.0.1:9200',
|
||||
'use_keystone': False,
|
||||
'match_pattern': '.*VERSION.*',
|
||||
'collect_response_time': True,
|
||||
'timeout': '10',
|
||||
'dimensions': {'service': 'logging'}},
|
||||
{'built_by': 'HttpCheck',
|
||||
'name': 'monasca',
|
||||
'url': 'http://192.168.10.6:8070',
|
||||
'use_keystone': False,
|
||||
'match_pattern': '.*OK.*',
|
||||
'collect_response_time': True,
|
||||
'timeout': '10',
|
||||
'dimensions': {'service': 'monitoring'}}]
|
||||
}
|
||||
```
|
||||
|
||||
#### Changing the current instance
|
||||
old_config:
|
||||
|
||||
```
|
||||
{'init_config': None,
|
||||
'instances': [{'built_by': 'HttpCheck',
|
||||
'name': 'logging',
|
||||
'url': 'http://192.168.10.6:8070',
|
||||
'use_keystone': False,
|
||||
'match_pattern': '.*VERSION.*',
|
||||
'collect_response_time': True,
|
||||
'timeout': '10',
|
||||
'dimensions': {'service': 'logging'}}]
|
||||
}
|
||||
```
|
||||
|
||||
monasca-setup arguments:
|
||||
|
||||
```
|
||||
monasca-setup -d 'HttpCheck' -a 'url=https://192.168.10.6:8070
|
||||
match_pattern=.*VERSION.* dimensions=service:logging'
|
||||
```
|
||||
|
||||
input_config generated from monasca-setup:
|
||||
|
||||
```
|
||||
{'http_check':
|
||||
{'instances': [{'built_by': 'HttpCheck',
|
||||
'name': 'https://192.168.10.6:8070',
|
||||
'url': 'https://192.168.10.6:8070',
|
||||
'use_keystone': False,
|
||||
'match_pattern': '.*VERSION.*',
|
||||
'collect_response_time': True,
|
||||
'dimensions': {'service': 'logging'}
|
||||
}]
|
||||
'init_config': None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
output_config from modify_config:
|
||||
|
||||
```
|
||||
{'init_config': None,
|
||||
'instances': [{'built_by': 'HttpCheck',
|
||||
'name': 'https://192.168.10.6:8070',
|
||||
'url': 'https://192.168.10.6:8070',
|
||||
'use_keystone': False,
|
||||
'match_pattern': '.*VERSION.*',
|
||||
'collect_response_time': True,
|
||||
'dimensions': {'service': 'logging'}
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
# License
|
||||
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development Company LP
|
||||
# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
|
||||
|
||||
"""Classes to aid in configuration of the agent."""
|
||||
|
||||
@ -102,6 +102,9 @@ def save_plugin_config(config_dir, plugin_name, user, conf):
|
||||
|
||||
|
||||
def check_endpoint_changes(value, config):
|
||||
"""Change urls in config with same path but different protocols into new
|
||||
endpoints.
|
||||
"""
|
||||
new_url = value['instances'][0]['url']
|
||||
old_urls = [i['url'] for i in config['instances'] if 'url' in i]
|
||||
new_path = new_url.split("://")[1]
|
||||
@ -111,7 +114,7 @@ def check_endpoint_changes(value, config):
|
||||
if config['instances'][i]['url'] == config['instances'][i]['name']:
|
||||
config['instances'][i]['name'] = new_url
|
||||
config['instances'][i]['url'] = new_url
|
||||
return value, config
|
||||
return config
|
||||
|
||||
|
||||
def delete_from_config(args, config, file_path, plugin_name):
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development Company LP
|
||||
# (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
|
||||
|
||||
""" Detect running daemons then configure and start the agent.
|
||||
"""
|
||||
@ -134,42 +134,64 @@ def base_configuration(args):
|
||||
|
||||
|
||||
def modify_config(args, detected_config):
|
||||
changes = False
|
||||
# Compare existing and detected config for each check plugin and write out the plugin config if changes
|
||||
for key, value in detected_config.iteritems():
|
||||
"""Compare existing and detected config for each check plugin and write out
|
||||
the plugin config if there are changes
|
||||
"""
|
||||
modified_config = False
|
||||
|
||||
for detection_plugin_name, new_config in detected_config.iteritems():
|
||||
if args.overwrite:
|
||||
changes = True
|
||||
modified_config = True
|
||||
if args.dry_run:
|
||||
continue
|
||||
else:
|
||||
agent_config.save_plugin_config(args.config_dir, key, args.user, value)
|
||||
agent_config.save_plugin_config(args.config_dir, detection_plugin_name, args.user, new_config)
|
||||
else:
|
||||
old_config = agent_config.read_plugin_config_from_disk(args.config_dir, key)
|
||||
config = agent_config.read_plugin_config_from_disk(args.config_dir, detection_plugin_name)
|
||||
# merge old and new config, new has precedence
|
||||
if old_config is not None:
|
||||
if key == "http_check":
|
||||
old_config_urls = [i['url'] for i in old_config['instances'] if 'url' in i]
|
||||
value, old_config = agent_config.check_endpoint_changes(value, old_config)
|
||||
agent_config.merge_by_name(value['instances'], old_config['instances'])
|
||||
# Sort before compare, if instances have no name the sort will fail making order changes significant
|
||||
if config is not None:
|
||||
# For HttpCheck, if the new input url has the same host and
|
||||
# port but a different protocol comparing with one of the
|
||||
# existing instances in http_check.yaml, we want to keep the
|
||||
# existing http check instance and replace the url with the
|
||||
# new protocol. If name in this instance is the same as the
|
||||
# url, we replace name with new url too.
|
||||
# For more details please see:
|
||||
# monasca-agent/docs/DeveloperDocs/agent_internals.md
|
||||
if detection_plugin_name == "http_check":
|
||||
# Save old http_check urls from config for later comparison
|
||||
config_urls = [i['url'] for i in config['instances'] if
|
||||
'url' in i]
|
||||
|
||||
# Check endpoint change, use new protocol instead
|
||||
# Note: config is possibly changed after running
|
||||
# check_endpoint_changes function.
|
||||
config = agent_config.check_endpoint_changes(new_config, config)
|
||||
|
||||
agent_config.merge_by_name(new_config['instances'], config['instances'])
|
||||
# Sort before compare, if instances have no name the sort will
|
||||
# fail making order changes significant
|
||||
try:
|
||||
value['instances'].sort(key=lambda k: k['name'])
|
||||
old_config['instances'].sort(key=lambda k: k['name'])
|
||||
new_config['instances'].sort(key=lambda k: k['name'])
|
||||
config['instances'].sort(key=lambda k: k['name'])
|
||||
except Exception:
|
||||
pass
|
||||
value_urls = [i['url'] for i in value['instances'] if 'url' in i]
|
||||
if key == "http_check":
|
||||
if value_urls == old_config_urls: # Don't write config if no change
|
||||
|
||||
if detection_plugin_name == "http_check":
|
||||
new_config_urls = [i['url'] for i in new_config['instances'] if 'url' in i]
|
||||
# Don't write config if no change
|
||||
if new_config_urls == config_urls and new_config == config:
|
||||
continue
|
||||
else:
|
||||
if value == old_config:
|
||||
if new_config == config:
|
||||
continue
|
||||
changes = True
|
||||
modified_config = True
|
||||
if args.dry_run:
|
||||
log.info("Changes would be made to the config file for the {0} check plugin".format(key))
|
||||
log.info("Changes would be made to the config file for the {0}"
|
||||
" check plugin".format(detection_plugin_name))
|
||||
else:
|
||||
agent_config.save_plugin_config(args.config_dir, key, args.user, value)
|
||||
return changes
|
||||
agent_config.save_plugin_config(args.config_dir, detection_plugin_name, args.user, new_config)
|
||||
return modified_config
|
||||
|
||||
|
||||
def validate_positive(value):
|
||||
|
261
tests/test_modify_config.py
Normal file
261
tests/test_modify_config.py
Normal file
@ -0,0 +1,261 @@
|
||||
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
|
||||
import collections
|
||||
import mock
|
||||
import unittest
|
||||
|
||||
import monasca_setup
|
||||
import monasca_setup.agent_config
|
||||
|
||||
DEFAULT_HTTP_CHECK_CONFIG = {
|
||||
'init_config': None,
|
||||
'instances': [{'built_by': 'HttpCheck',
|
||||
'match_pattern': '.*VERSION.*',
|
||||
'url': 'http://127.0.0.1:9200',
|
||||
'name': 'logging',
|
||||
'timeout': '10',
|
||||
'collect_response_time': True,
|
||||
'use_keystone': False,
|
||||
'dimensions': {'service': 'logging'}}]
|
||||
}
|
||||
|
||||
DEFAULT_PROCESS_CHECK_CONFIG = {
|
||||
'init_config': None,
|
||||
'instances': [{'built_by': 'MonNotification',
|
||||
'detailed': True,
|
||||
'dimensions': {'component': 'monasca-notification'},
|
||||
'exact_match': False,
|
||||
'name': 'monasca-notification',
|
||||
'search_string': ['monasca-notification']
|
||||
}]
|
||||
}
|
||||
|
||||
INPUT_ARGS = collections.namedtuple(
|
||||
"InputArgs", ["overwrite", "user", "config_dir", "detection_args",
|
||||
"detection_plugins", "dry_run"])
|
||||
|
||||
|
||||
class TestModifyConfig(unittest.TestCase):
|
||||
""" Unit tests for modify_config function in monasca_setup/main.py
|
||||
More details are documented in:
|
||||
monasca-agent/docs/DeveloperDocs/agent_internals.md
|
||||
"""
|
||||
def setUp(self):
|
||||
self._config_data = {}
|
||||
|
||||
def save_config(self, config_dir, plugin_name, user, data):
|
||||
self._config_data = data
|
||||
|
||||
@mock.patch('monasca_setup.main.agent_config.save_plugin_config')
|
||||
@mock.patch('monasca_setup.main.agent_config.read_plugin_config_from_disk')
|
||||
def test_no_modify_process_check_config(self, mock_read_config,
|
||||
mock_save_config):
|
||||
mock_read_config.return_value = DEFAULT_PROCESS_CHECK_CONFIG
|
||||
mock_save_config.side_effect = self.save_config
|
||||
|
||||
# Add a new process check instance
|
||||
same_built_by = DEFAULT_PROCESS_CHECK_CONFIG['instances'][0][
|
||||
'built_by']
|
||||
same_name = DEFAULT_PROCESS_CHECK_CONFIG['instances'][0][
|
||||
'name']
|
||||
args, detected_config = self._get_mon_api_check_args_and_config(
|
||||
same_built_by, same_name)
|
||||
self._check_no_change(args, detected_config)
|
||||
|
||||
@mock.patch('monasca_setup.main.agent_config.save_plugin_config')
|
||||
@mock.patch('monasca_setup.main.agent_config.read_plugin_config_from_disk')
|
||||
def test_modify_process_check_config(self, mock_read_config,
|
||||
mock_save_config):
|
||||
mock_read_config.return_value = DEFAULT_PROCESS_CHECK_CONFIG
|
||||
mock_save_config.side_effect = self.save_config
|
||||
|
||||
# Add a new process check instance
|
||||
built_by = 'MonAPI'
|
||||
name = 'monasca-api'
|
||||
args, detected_config = self._get_mon_api_check_args_and_config(
|
||||
built_by, name)
|
||||
expected_value = \
|
||||
{'init_config': None,
|
||||
'instances': [{'built_by': built_by,
|
||||
'detailed': True,
|
||||
'dimensions': {'component': 'monasca-api'},
|
||||
'exact_match': False,
|
||||
'name': name,
|
||||
'search_string': ['monasca-api']
|
||||
},
|
||||
DEFAULT_PROCESS_CHECK_CONFIG['instances'][0]]
|
||||
}
|
||||
self._check_changes(args, detected_config, expected_value)
|
||||
|
||||
@mock.patch('monasca_setup.main.agent_config.save_plugin_config')
|
||||
@mock.patch('monasca_setup.main.agent_config.read_plugin_config_from_disk')
|
||||
def test_no_modify_http_check_config(self, mock_read_config,
|
||||
mock_save_config):
|
||||
mock_read_config.return_value = DEFAULT_HTTP_CHECK_CONFIG
|
||||
mock_save_config.side_effect = self.save_config
|
||||
|
||||
# keep url and match_pattern are the same
|
||||
same_url = DEFAULT_HTTP_CHECK_CONFIG['instances'][0]['url']
|
||||
same_match_pattern = DEFAULT_HTTP_CHECK_CONFIG['instances'][0][
|
||||
'match_pattern']
|
||||
same_name = DEFAULT_HTTP_CHECK_CONFIG['instances'][0]['name']
|
||||
|
||||
args, detected_config = self. _get_http_check_args_and_config(
|
||||
same_url, same_match_pattern, same_name)
|
||||
self._check_no_change(args, detected_config)
|
||||
|
||||
@mock.patch('monasca_setup.main.agent_config.save_plugin_config')
|
||||
@mock.patch('monasca_setup.main.agent_config.read_plugin_config_from_disk')
|
||||
def test_modify_http_check_config(self, mock_read_config,
|
||||
mock_save_config):
|
||||
mock_read_config.return_value = DEFAULT_HTTP_CHECK_CONFIG
|
||||
mock_save_config.side_effect = self.save_config
|
||||
|
||||
# Change protocol and match_pattern
|
||||
url = 'https://127.0.0.1:9200'
|
||||
match_pattern = '.*OK.*'
|
||||
|
||||
args, detected_config = self. _get_http_check_args_and_config(
|
||||
url, match_pattern, 'logging')
|
||||
expected_value = {'init_config': None,
|
||||
'instances':
|
||||
[{'built_by': 'HttpCheck',
|
||||
'collect_response_time': True,
|
||||
'url': url,
|
||||
'match_pattern': match_pattern,
|
||||
'name': 'logging',
|
||||
'timeout': '10',
|
||||
'use_keystone': False,
|
||||
'dimensions': {'service': 'logging'}}]
|
||||
}
|
||||
self._check_changes(args, detected_config, expected_value)
|
||||
|
||||
@mock.patch('monasca_setup.main.agent_config.save_plugin_config')
|
||||
@mock.patch('monasca_setup.main.agent_config.read_plugin_config_from_disk')
|
||||
def test_http_check_endpoint_change(self, mock_read_config,
|
||||
mock_save_config):
|
||||
mock_read_config.return_value = DEFAULT_HTTP_CHECK_CONFIG
|
||||
mock_save_config.side_effect = self.save_config
|
||||
|
||||
# Change only protocol
|
||||
new_url = 'https://127.0.0.1:9200'
|
||||
same_match_pattern = DEFAULT_HTTP_CHECK_CONFIG['instances'][0][
|
||||
'match_pattern']
|
||||
same_name = DEFAULT_HTTP_CHECK_CONFIG['instances'][0]['name']
|
||||
args, detected_config = self. _get_http_check_args_and_config(
|
||||
new_url, same_match_pattern, same_name)
|
||||
expected_value = {'init_config': None,
|
||||
'instances':
|
||||
[{'built_by': 'HttpCheck',
|
||||
'collect_response_time': True,
|
||||
'url': new_url,
|
||||
'match_pattern': same_match_pattern,
|
||||
'name': same_name,
|
||||
'timeout': '10',
|
||||
'use_keystone': False,
|
||||
'dimensions': {'service': 'logging'}}]
|
||||
}
|
||||
self._check_changes(args, detected_config, expected_value)
|
||||
|
||||
@mock.patch('monasca_setup.main.agent_config.save_plugin_config')
|
||||
@mock.patch('monasca_setup.main.agent_config.read_plugin_config_from_disk')
|
||||
def test_http_check_only_match_pattern(self, mock_read_config,
|
||||
mock_save_config):
|
||||
mock_read_config.return_value = DEFAULT_HTTP_CHECK_CONFIG
|
||||
mock_save_config.side_effect = self.save_config
|
||||
|
||||
# Change only match_pattern
|
||||
same_url = DEFAULT_HTTP_CHECK_CONFIG['instances'][0]['url']
|
||||
new_match_pattern = '.*TEST.*'
|
||||
same_name = DEFAULT_HTTP_CHECK_CONFIG['instances'][0]['name']
|
||||
args, detected_config = self. _get_http_check_args_and_config(
|
||||
same_url, new_match_pattern, same_name)
|
||||
expected_value = {'init_config': None,
|
||||
'instances':
|
||||
[{'built_by': 'HttpCheck',
|
||||
'collect_response_time': True,
|
||||
'url': same_url,
|
||||
'match_pattern': new_match_pattern,
|
||||
'name': same_name,
|
||||
'timeout': '10',
|
||||
'use_keystone': False,
|
||||
'dimensions': {'service': 'logging'}}]
|
||||
}
|
||||
self._check_changes(args, detected_config, expected_value)
|
||||
|
||||
@mock.patch('monasca_setup.main.agent_config.save_plugin_config')
|
||||
@mock.patch('monasca_setup.main.agent_config.read_plugin_config_from_disk')
|
||||
def test_http_check_new_url(self, mock_read_config, mock_save_config):
|
||||
mock_read_config.return_value = DEFAULT_HTTP_CHECK_CONFIG
|
||||
mock_save_config.side_effect = self.save_config
|
||||
|
||||
# Pass in a new url
|
||||
new_url = 'http://192.168.10.6:8070'
|
||||
new_match_pattern = '.*TEST.*'
|
||||
new_name = new_url
|
||||
args, detected_config = self. _get_http_check_args_and_config(
|
||||
new_url, new_match_pattern, new_name)
|
||||
expected_value = {'init_config': None,
|
||||
'instances':
|
||||
[{'built_by': 'HttpCheck',
|
||||
'collect_response_time': True,
|
||||
'url': new_url,
|
||||
'match_pattern': new_match_pattern,
|
||||
'name': new_name,
|
||||
'timeout': '10',
|
||||
'use_keystone': False,
|
||||
'dimensions': {'service': 'logging'}},
|
||||
DEFAULT_HTTP_CHECK_CONFIG['instances'][0]
|
||||
]
|
||||
}
|
||||
self._check_changes(args, detected_config, expected_value)
|
||||
|
||||
def _check_no_change(self, args, detected_config):
|
||||
changes = monasca_setup.main.modify_config(args, detected_config)
|
||||
self.assertEqual(changes, False)
|
||||
self.assertEqual(self._config_data, {})
|
||||
|
||||
def _check_changes(self, args, detected_config, expected_value):
|
||||
changes = monasca_setup.main.modify_config(args, detected_config)
|
||||
self.assertEqual(changes, True)
|
||||
self.assertEqual(expected_value, self._config_data)
|
||||
|
||||
def _get_mon_api_check_args_and_config(self, built_by, name):
|
||||
args = INPUT_ARGS(False, 'mon-agent', '/etc/monasca/agent', None,
|
||||
['MonAPI'], False)
|
||||
detected_config = {
|
||||
'process':
|
||||
{'instances': [{'built_by': built_by,
|
||||
'detailed': True,
|
||||
'dimensions': {
|
||||
'component': name},
|
||||
'exact_match': False,
|
||||
'name': name,
|
||||
'search_string': [name]
|
||||
}],
|
||||
'init_config': None
|
||||
}
|
||||
}
|
||||
return args, detected_config
|
||||
|
||||
def _get_http_check_args_and_config(self, url, match_pattern, name):
|
||||
args = INPUT_ARGS(False, 'mon-agent', '/etc/monasca/agent',
|
||||
'url={0} match_pattern={1} name={2} timeout=10 '
|
||||
'use_keystone=False'.format(
|
||||
url, match_pattern, name),
|
||||
['HttpCheck'], False)
|
||||
detected_config = {
|
||||
'http_check':
|
||||
{'instances': [{'name': name,
|
||||
'url': url,
|
||||
'built_by': 'HttpCheck',
|
||||
'use_keystone': False,
|
||||
'match_pattern': match_pattern,
|
||||
'collect_response_time': True,
|
||||
'timeout': '10',
|
||||
'dimensions': {'service': 'logging'}
|
||||
}],
|
||||
'init_config': None
|
||||
}
|
||||
}
|
||||
return args, detected_config
|
Loading…
x
Reference in New Issue
Block a user