Skip to content

Commit 76b23f3

Browse files
committed
Adding support for JSON service discovery config
1 parent 15b42d6 commit 76b23f3

2 files changed

Lines changed: 76 additions & 1 deletion

File tree

utils/service_discovery/config_stores.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
from utils.service_discovery.etcd_config_store import EtcdStore
1010
from utils.service_discovery.consul_config_store import ConsulStore
1111
from utils.service_discovery.zookeeper_config_store import ZookeeperStore
12+
from utils.service_discovery.json_file_config_store import JsonStore
1213

13-
SD_CONFIG_BACKENDS = ['etcd', 'consul', 'zk'] # noqa: used somewhere else
14+
SD_CONFIG_BACKENDS = ['etcd', 'consul', 'zk', 'json'] # noqa: used somewhere else
1415
SD_TEMPLATE_DIR = '/datadog/check_configs'
1516

1617

@@ -21,6 +22,8 @@ def get_config_store(agentConfig):
2122
return ConsulStore(agentConfig)
2223
elif agentConfig.get('sd_config_backend') == 'zk':
2324
return ZookeeperStore(agentConfig)
25+
elif agentConfig.get('sd_config_backend') == 'json':
26+
return JsonStore(agentConfig)
2427
else:
2528
return StubStore(agentConfig)
2629

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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

Comments
 (0)