diff --git a/chaos_monkey/__init__.py b/chaos_monkey/__init__.py deleted file mode 100644 index 05a457b0cee..00000000000 --- a/chaos_monkey/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'itamar' diff --git a/chaos_monkey/config.py b/chaos_monkey/config.py index addb9fd54b4..b26c911b06e 100644 --- a/chaos_monkey/config.py +++ b/chaos_monkey/config.py @@ -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 @@ def from_dict(self, data): 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 = {} diff --git a/chaos_monkey/control.py b/chaos_monkey/control.py index f8f3e3ee01d..cdeb47a766c 100644 --- a/chaos_monkey/control.py +++ b/chaos_monkey/control.py @@ -124,7 +124,7 @@ def load_control_config(): 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 @@ def load_control_config(): 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() diff --git a/chaos_monkey/requirements.txt b/chaos_monkey/requirements.txt index 8c77333f9e2..34f24c78f1d 100644 --- a/chaos_monkey/requirements.txt +++ b/chaos_monkey/requirements.txt @@ -12,3 +12,5 @@ psutil PyInstaller ecdsa netifaces +mock +nose diff --git a/monkey_island/cc/main.py b/monkey_island/cc/main.py index ccf3fe995eb..b05c42e7044 100644 --- a/monkey_island/cc/main.py +++ b/monkey_island/cc/main.py @@ -86,6 +86,8 @@ def patch(self, guid): 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)