Skip to content

Commit

Permalink
Adding support for JSON service discovery config
Browse files Browse the repository at this point in the history
  • Loading branch information
sdwr98 committed Mar 14, 2017
1 parent 15b42d6 commit 07e3519
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 1 deletion.
5 changes: 4 additions & 1 deletion utils/service_discovery/config_stores.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
from utils.service_discovery.etcd_config_store import EtcdStore
from utils.service_discovery.consul_config_store import ConsulStore
from utils.service_discovery.zookeeper_config_store import ZookeeperStore
from utils.service_discovery.json_file_config_store import JsonStore

SD_CONFIG_BACKENDS = ['etcd', 'consul', 'zk'] # noqa: used somewhere else
SD_CONFIG_BACKENDS = ['etcd', 'consul', 'zk', 'json'] # noqa: used somewhere else
SD_TEMPLATE_DIR = '/datadog/check_configs'


Expand All @@ -21,6 +22,8 @@ def get_config_store(agentConfig):
return ConsulStore(agentConfig)
elif agentConfig.get('sd_config_backend') == 'zk':
return ZookeeperStore(agentConfig)
elif agentConfig.get('sd_config_backend') == 'json':
return JsonStore(agentConfig)
else:
return StubStore(agentConfig)

Expand Down
70 changes: 70 additions & 0 deletions utils/service_discovery/json_file_config_store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# (C) Datadog, Inc. 2010-2016
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)

# std
import logging
import simplejson as json

# project
from utils.service_discovery.abstract_config_store import AbstractConfigStore, KeyNotFound

DEFAULT_FILE_PATH = '/etc/dd-agent/sd.json'
log = logging.getLogger(__name__)

class JsonStore(AbstractConfigStore):
"""Implementation of a config store client for flat json files"""
def _extract_settings(self, config):
"""Extract settings from a config object"""
settings = {
'file_path': config.get('sd_json_file_path', DEFAULT_FILE_PATH),
}
return settings

def get_client(self, reset=False):
"""Return a file client, create it if needed"""
if self.client is None or reset is True:
with open(self.settings.get('file_path')) as f:
self.client = json.load(f)
return self.client

def client_read(self, path, **kwargs):
"""Retrieve a value from the json dict."""
if kwargs.get('watch', False):
# json file never reloads
return 0

if kwargs.get('all', False):
# This wants a list of tuples with the first element of the tuple
# being the path and the second element of the tuple being json.
# This is 2 levels past the depth of the sd_template_dir
return self._get_as_path_items(self.client, len(self.sd_template_dir.split("/")) + 2)
else:
res = self._get_nested_path(self.client, path)
if res is not None:
return json.dumps(res)
else:
raise KeyNotFound("The key %s was not found in the json file" % path)

def _get_as_path_items(self, data, depth, prefix = ""):
results = []
if depth == 1:
for key in data.iterkeys():
keystr = prefix.lstrip("/") + "/" + key
results.append((keystr, json.dumps(data[key])))
else:
for key in data.iterkeys():
prefix = prefix + "/" + key
results.extend(self._get_as_path_items(data[key], depth - 1, prefix))

return results

def _get_nested_path(self, data, path):
path_elements = path.split('/')
if data is None:
return None
elif len(path_elements) > 1:
first_element = path_elements[0]
return self._get_nested_path(data.get(first_element), "/".join(path_elements[1:]))
else:
return data.get(path_elements[0])

0 comments on commit 07e3519

Please sign in to comment.