|
| 1 | +# (C) Datadog, Inc. 2010-2016 |
| 2 | +# All rights reserved |
| 3 | +# Licensed under Simplified BSD License (see LICENSE) |
| 4 | + |
| 5 | +# std |
| 6 | +import logging |
| 7 | +import simplejson as json |
| 8 | + |
| 9 | +# project |
| 10 | +from utils.service_discovery.abstract_config_store import AbstractConfigStore, KeyNotFound |
| 11 | + |
| 12 | +DEFAULT_FILE_PATH = '/etc/dd-agent/sd.json' |
| 13 | +log = logging.getLogger(__name__) |
| 14 | + |
| 15 | +class JsonStore(AbstractConfigStore): |
| 16 | + """Implementation of a config store client for flat json files""" |
| 17 | + def _extract_settings(self, config): |
| 18 | + """Extract settings from a config object""" |
| 19 | + settings = { |
| 20 | + 'file_path': config.get('sd_json_file_path', DEFAULT_FILE_PATH), |
| 21 | + } |
| 22 | + return settings |
| 23 | + |
| 24 | + def get_client(self, reset=False): |
| 25 | + """Return a file client, create it if needed""" |
| 26 | + if self.client is None or reset is True: |
| 27 | + with open(self.settings.get('file_path')) as f: |
| 28 | + self.client = json.load(f) |
| 29 | + return self.client |
| 30 | + |
| 31 | + def client_read(self, path, **kwargs): |
| 32 | + """Retrieve a value from the json dict.""" |
| 33 | + if kwargs.get('watch', False): |
| 34 | + # json file never reloads |
| 35 | + return 0 |
| 36 | + |
| 37 | + recurse = kwargs.get('recursive') or kwargs.get('all', False) |
| 38 | + |
| 39 | + if kwargs.get('all', False): |
| 40 | + # This wants a list of tuples with the first element of the tuple |
| 41 | + # being the path and the second element of the tuple being json. |
| 42 | + # This is 2 levels past the depth of the sd_template_dir |
| 43 | + return self._get_as_path_items(self.client, len(self.sd_template_dir.split("/")) + 2) |
| 44 | + else: |
| 45 | + res = self._get_nested_path(self.client, path) |
| 46 | + if res is not None: |
| 47 | + return json.dumps(res) |
| 48 | + else: |
| 49 | + raise KeyNotFound("The key %s was not found in the json file" % path) |
| 50 | + |
| 51 | + def _get_as_path_items(self, data, depth, prefix = ""): |
| 52 | + results = [] |
| 53 | + if depth == 1: |
| 54 | + for key in data.iterkeys(): |
| 55 | + keystr = prefix.lstrip("/") + "/" + key |
| 56 | + results.append((keystr, json.dumps(data[key]))) |
| 57 | + else: |
| 58 | + for key in data.iterkeys(): |
| 59 | + prefix = prefix + "/" + key |
| 60 | + results.extend(self._get_as_path_items(data[key], depth - 1, prefix)) |
| 61 | + |
| 62 | + return results |
| 63 | + |
| 64 | + def _get_nested_path(self, data, path): |
| 65 | + path_elements = path.split('/') |
| 66 | + if data is None: |
| 67 | + return None |
| 68 | + elif len(path_elements) > 1: |
| 69 | + first_element = path_elements[0] |
| 70 | + return self._get_nested_path(data.get(first_element), "/".join(path_elements[1:])) |
| 71 | + else: |
| 72 | + return data.get(path_elements[0]) |
0 commit comments