forked from p34709852/monkey
Merge pull request #38 from Fak3/f26
Don't crash when receiving unknown configuration variables
This commit is contained in:
commit
3ef24281a7
|
@ -1 +0,0 @@
|
|||
__author__ = 'itamar'
|
|
@ -45,6 +45,11 @@ def _cast_by_example(value, example):
|
|||
|
||||
class Configuration(object):
|
||||
def from_dict(self, data):
|
||||
"""
|
||||
Get a dict of config variables, set known variables as attributes on self.
|
||||
Return dict of unknown variables encountered.
|
||||
"""
|
||||
unknown_variables = {}
|
||||
for key, value in data.items():
|
||||
if key.startswith('_'):
|
||||
continue
|
||||
|
@ -55,9 +60,11 @@ class Configuration(object):
|
|||
try:
|
||||
default_value = getattr(Configuration, key)
|
||||
except AttributeError:
|
||||
raise
|
||||
unknown_variables[key] = value
|
||||
continue
|
||||
|
||||
setattr(self, key, _cast_by_example(value, default_value))
|
||||
return unknown_variables
|
||||
|
||||
def as_dict(self):
|
||||
result = {}
|
||||
|
|
|
@ -124,7 +124,7 @@ class ControlClient(object):
|
|||
return
|
||||
|
||||
try:
|
||||
WormConfiguration.from_dict(reply.json().get('config'))
|
||||
unknown_variables = WormConfiguration.from_dict(reply.json().get('config'))
|
||||
LOG.info("New configuration was loaded from server: %r" % (WormConfiguration.as_dict(),))
|
||||
except Exception, exc:
|
||||
# we don't continue with default conf here because it might be dangerous
|
||||
|
@ -132,6 +132,23 @@ class ControlClient(object):
|
|||
WormConfiguration.current_server, reply._content, exc)
|
||||
raise Exception("Couldn't load from from server's configuration, aborting. %s" % exc)
|
||||
|
||||
if unknown_variables:
|
||||
ControlClient.send_config_error()
|
||||
|
||||
@staticmethod
|
||||
def send_config_error():
|
||||
if not WormConfiguration.current_server:
|
||||
return
|
||||
try:
|
||||
requests.patch("https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID),
|
||||
data=json.dumps({'config_error': True}),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
proxies=ControlClient.proxies)
|
||||
except Exception, exc:
|
||||
LOG.warn("Error connecting to control server %s: %s", WormConfiguration.current_server, exc)
|
||||
return {}
|
||||
|
||||
@staticmethod
|
||||
def check_for_stop():
|
||||
ControlClient.load_control_config()
|
||||
|
|
|
@ -12,3 +12,5 @@ psutil
|
|||
PyInstaller
|
||||
ecdsa
|
||||
netifaces
|
||||
mock
|
||||
nose
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
# NOTE: Launch all tests with `nosetests` command from chaos_monkey dir.
|
||||
|
||||
import json
|
||||
import unittest
|
||||
|
||||
from mock import Mock, patch
|
||||
|
||||
import control
|
||||
|
||||
from config import GUID
|
||||
|
||||
|
||||
class ReportConfigErrorTestCase(unittest.TestCase):
|
||||
"""
|
||||
When unknown config variable received form the island server, skip it and report config
|
||||
error back to the server.
|
||||
"""
|
||||
|
||||
config_response = Mock(json=Mock(return_value={'config': {'blah': 'blah'}}))
|
||||
|
||||
def teardown(self):
|
||||
patch.stopall()
|
||||
|
||||
def test_config(self):
|
||||
patch('control.requests.patch', Mock()).start()
|
||||
patch('control.WormConfiguration', Mock(current_server='127.0.0.1:123')).start()
|
||||
|
||||
# GIVEN the server with uknown config variable
|
||||
patch('control.requests.get', Mock(return_value=self.config_response)).start()
|
||||
|
||||
# WHEN monkey tries to load config from server
|
||||
control.ControlClient.load_control_config()
|
||||
|
||||
# THEN she reports config error back to the server
|
||||
control.requests.patch.assert_called_once_with(
|
||||
"https://127.0.0.1:123/api/monkey/%s" % GUID,
|
||||
data=json.dumps({'config_error': True}),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
proxies=control.ControlClient.proxies)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
|
@ -86,6 +86,8 @@ class Monkey(restful.Resource):
|
|||
update['$set']['config'] = monkey_json['config']
|
||||
if 'tunnel' in monkey_json:
|
||||
update['$set']['tunnel'] = monkey_json['tunnel']
|
||||
if 'config_error' in monkey_json:
|
||||
update['$set']['config_error'] = monkey_json['config_error']
|
||||
|
||||
return mongo.db.monkey.update({"guid": guid}, update, upsert=False)
|
||||
|
||||
|
|
Loading…
Reference in New Issue