gen_integrations.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. #!/usr/bin/env python3
  2. import json
  3. import os
  4. import re
  5. import sys
  6. from copy import deepcopy
  7. from pathlib import Path
  8. from jsonschema import Draft7Validator, ValidationError
  9. from referencing import Registry, Resource
  10. from referencing.jsonschema import DRAFT7
  11. from ruamel.yaml import YAML, YAMLError
  12. AGENT_REPO = 'netdata/netdata'
  13. INTEGRATIONS_PATH = Path(__file__).parent
  14. TEMPLATE_PATH = INTEGRATIONS_PATH / 'templates'
  15. OUTPUT_PATH = INTEGRATIONS_PATH / 'integrations.js'
  16. JSON_PATH = INTEGRATIONS_PATH / 'integrations.json'
  17. CATEGORIES_FILE = INTEGRATIONS_PATH / 'categories.yaml'
  18. REPO_PATH = INTEGRATIONS_PATH.parent
  19. SCHEMA_PATH = INTEGRATIONS_PATH / 'schemas'
  20. DISTROS_FILE = REPO_PATH / '.github' / 'data' / 'distros.yml'
  21. METADATA_PATTERN = '*/metadata.yaml'
  22. COLLECTOR_SOURCES = [
  23. (AGENT_REPO, REPO_PATH / 'src' / 'collectors', True),
  24. (AGENT_REPO, REPO_PATH / 'src' / 'collectors' / 'charts.d.plugin', True),
  25. (AGENT_REPO, REPO_PATH / 'src' / 'collectors' / 'python.d.plugin', True),
  26. (AGENT_REPO, REPO_PATH / 'src' / 'go' / 'collectors' / 'go.d.plugin' / 'modules', True),
  27. ]
  28. DEPLOY_SOURCES = [
  29. (AGENT_REPO, INTEGRATIONS_PATH / 'deploy.yaml', False),
  30. ]
  31. EXPORTER_SOURCES = [
  32. (AGENT_REPO, REPO_PATH / 'src' / 'exporting', True),
  33. ]
  34. NOTIFICATION_SOURCES = [
  35. (AGENT_REPO, REPO_PATH / 'src' / 'health' / 'notifications', True),
  36. (AGENT_REPO, INTEGRATIONS_PATH / 'cloud-notifications' / 'metadata.yaml', False),
  37. ]
  38. AUTHENTICATION_SOURCES = [
  39. (AGENT_REPO, INTEGRATIONS_PATH / 'cloud-authentication' / 'metadata.yaml', False),
  40. ]
  41. COLLECTOR_RENDER_KEYS = [
  42. 'alerts',
  43. 'metrics',
  44. 'overview',
  45. 'related_resources',
  46. 'setup',
  47. 'troubleshooting',
  48. ]
  49. EXPORTER_RENDER_KEYS = [
  50. 'overview',
  51. 'setup',
  52. 'troubleshooting',
  53. ]
  54. NOTIFICATION_RENDER_KEYS = [
  55. 'overview',
  56. 'setup',
  57. 'troubleshooting',
  58. ]
  59. AUTHENTICATION_RENDER_KEYS = [
  60. 'overview',
  61. 'setup',
  62. 'troubleshooting',
  63. ]
  64. CUSTOM_TAG_PATTERN = re.compile('\\{% if .*?%\\}.*?\\{% /if %\\}|\\{%.*?%\\}', flags=re.DOTALL)
  65. FIXUP_BLANK_PATTERN = re.compile('\\\\\\n *\\n')
  66. GITHUB_ACTIONS = os.environ.get('GITHUB_ACTIONS', False)
  67. DEBUG = os.environ.get('DEBUG', False)
  68. def debug(msg):
  69. if GITHUB_ACTIONS:
  70. print(f':debug:{ msg }')
  71. elif DEBUG:
  72. print(f'>>> { msg }')
  73. else:
  74. pass
  75. def warn(msg, path):
  76. if GITHUB_ACTIONS:
  77. print(f':warning file={ path }:{ msg }')
  78. else:
  79. print(f'!!! WARNING:{ path }:{ msg }')
  80. def retrieve_from_filesystem(uri):
  81. path = SCHEMA_PATH / Path(uri)
  82. contents = json.loads(path.read_text())
  83. return Resource.from_contents(contents, DRAFT7)
  84. registry = Registry(retrieve=retrieve_from_filesystem)
  85. CATEGORY_VALIDATOR = Draft7Validator(
  86. {'$ref': './categories.json#'},
  87. registry=registry,
  88. )
  89. DEPLOY_VALIDATOR = Draft7Validator(
  90. {'$ref': './deploy.json#'},
  91. registry=registry,
  92. )
  93. EXPORTER_VALIDATOR = Draft7Validator(
  94. {'$ref': './exporter.json#'},
  95. registry=registry,
  96. )
  97. NOTIFICATION_VALIDATOR = Draft7Validator(
  98. {'$ref': './notification.json#'},
  99. registry=registry,
  100. )
  101. AUTHENTICATION_VALIDATOR = Draft7Validator(
  102. {'$ref': './authentication.json#'},
  103. registry=registry,
  104. )
  105. COLLECTOR_VALIDATOR = Draft7Validator(
  106. {'$ref': './collector.json#'},
  107. registry=registry,
  108. )
  109. _jinja_env = False
  110. def get_jinja_env():
  111. global _jinja_env
  112. if not _jinja_env:
  113. from jinja2 import Environment, FileSystemLoader, select_autoescape
  114. _jinja_env = Environment(
  115. loader=FileSystemLoader(TEMPLATE_PATH),
  116. autoescape=select_autoescape(),
  117. block_start_string='[%',
  118. block_end_string='%]',
  119. variable_start_string='[[',
  120. variable_end_string=']]',
  121. comment_start_string='[#',
  122. comment_end_string='#]',
  123. trim_blocks=True,
  124. lstrip_blocks=True,
  125. )
  126. _jinja_env.globals.update(strfy=strfy)
  127. return _jinja_env
  128. def strfy(value):
  129. if isinstance(value, bool):
  130. return "yes" if value else "no"
  131. if isinstance(value, str):
  132. return ' '.join([v.strip() for v in value.strip().split("\n") if v]).replace('|', '/')
  133. return value
  134. def get_category_sets(categories):
  135. default = set()
  136. valid = set()
  137. for c in categories:
  138. if 'id' in c:
  139. valid.add(c['id'])
  140. if c.get('collector_default', False):
  141. default.add(c['id'])
  142. if 'children' in c and c['children']:
  143. d, v = get_category_sets(c['children'])
  144. default |= d
  145. valid |= v
  146. return (default, valid)
  147. def get_collector_metadata_entries():
  148. ret = []
  149. for r, d, m in COLLECTOR_SOURCES:
  150. if d.exists() and d.is_dir() and m:
  151. for item in d.glob(METADATA_PATTERN):
  152. ret.append((r, item))
  153. elif d.exists() and d.is_file() and not m:
  154. if d.match(METADATA_PATTERN):
  155. ret.append(d)
  156. return ret
  157. def load_yaml(src):
  158. yaml = YAML(typ='safe')
  159. if not src.is_file():
  160. warn(f'{ src } is not a file.', src)
  161. return False
  162. try:
  163. contents = src.read_text()
  164. except (IOError, OSError):
  165. warn(f'Failed to read { src }.', src)
  166. return False
  167. try:
  168. data = yaml.load(contents)
  169. except YAMLError:
  170. warn(f'Failed to parse { src } as YAML.', src)
  171. return False
  172. return data
  173. def load_categories():
  174. categories = load_yaml(CATEGORIES_FILE)
  175. if not categories:
  176. sys.exit(1)
  177. try:
  178. CATEGORY_VALIDATOR.validate(categories)
  179. except ValidationError:
  180. warn(f'Failed to validate { CATEGORIES_FILE } against the schema.', CATEGORIES_FILE)
  181. sys.exit(1)
  182. return categories
  183. def load_collectors():
  184. ret = []
  185. entries = get_collector_metadata_entries()
  186. for repo, path in entries:
  187. debug(f'Loading { path }.')
  188. data = load_yaml(path)
  189. if not data:
  190. continue
  191. try:
  192. COLLECTOR_VALIDATOR.validate(data)
  193. except ValidationError:
  194. warn(f'Failed to validate { path } against the schema.', path)
  195. continue
  196. for idx, item in enumerate(data['modules']):
  197. item['meta']['plugin_name'] = data['plugin_name']
  198. item['integration_type'] = 'collector'
  199. item['_src_path'] = path
  200. item['_repo'] = repo
  201. item['_index'] = idx
  202. ret.append(item)
  203. return ret
  204. def _load_deploy_file(file, repo):
  205. ret = []
  206. debug(f'Loading { file }.')
  207. data = load_yaml(file)
  208. if not data:
  209. return []
  210. try:
  211. DEPLOY_VALIDATOR.validate(data)
  212. except ValidationError:
  213. warn(f'Failed to validate { file } against the schema.', file)
  214. return []
  215. for idx, item in enumerate(data):
  216. item['integration_type'] = 'deploy'
  217. item['_src_path'] = file
  218. item['_repo'] = repo
  219. item['_index'] = idx
  220. ret.append(item)
  221. return ret
  222. def load_deploy():
  223. ret = []
  224. for repo, path, match in DEPLOY_SOURCES:
  225. if match and path.exists() and path.is_dir():
  226. for file in path.glob(METADATA_PATTERN):
  227. ret.extend(_load_deploy_file(file, repo))
  228. elif not match and path.exists() and path.is_file():
  229. ret.extend(_load_deploy_file(path, repo))
  230. return ret
  231. def _load_exporter_file(file, repo):
  232. debug(f'Loading { file }.')
  233. data = load_yaml(file)
  234. if not data:
  235. return []
  236. try:
  237. EXPORTER_VALIDATOR.validate(data)
  238. except ValidationError:
  239. warn(f'Failed to validate { file } against the schema.', file)
  240. return []
  241. if 'id' in data:
  242. data['integration_type'] = 'exporter'
  243. data['_src_path'] = file
  244. data['_repo'] = repo
  245. data['_index'] = 0
  246. return [data]
  247. else:
  248. ret = []
  249. for idx, item in enumerate(data):
  250. item['integration_type'] = 'exporter'
  251. item['_src_path'] = file
  252. item['_repo'] = repo
  253. item['_index'] = idx
  254. ret.append(item)
  255. return ret
  256. def load_exporters():
  257. ret = []
  258. for repo, path, match in EXPORTER_SOURCES:
  259. if match and path.exists() and path.is_dir():
  260. for file in path.glob(METADATA_PATTERN):
  261. ret.extend(_load_exporter_file(file, repo))
  262. elif not match and path.exists() and path.is_file():
  263. ret.extend(_load_exporter_file(path, repo))
  264. return ret
  265. def _load_notification_file(file, repo):
  266. debug(f'Loading { file }.')
  267. data = load_yaml(file)
  268. if not data:
  269. return []
  270. try:
  271. NOTIFICATION_VALIDATOR.validate(data)
  272. except ValidationError:
  273. warn(f'Failed to validate { file } against the schema.', file)
  274. return []
  275. if 'id' in data:
  276. data['integration_type'] = 'notification'
  277. data['_src_path'] = file
  278. data['_repo'] = repo
  279. data['_index'] = 0
  280. return [data]
  281. else:
  282. ret = []
  283. for idx, item in enumerate(data):
  284. item['integration_type'] = 'notification'
  285. item['_src_path'] = file
  286. item['_repo'] = repo
  287. item['_index'] = idx
  288. ret.append(item)
  289. return ret
  290. def load_notifications():
  291. ret = []
  292. for repo, path, match in NOTIFICATION_SOURCES:
  293. if match and path.exists() and path.is_dir():
  294. for file in path.glob(METADATA_PATTERN):
  295. ret.extend(_load_notification_file(file, repo))
  296. elif not match and path.exists() and path.is_file():
  297. ret.extend(_load_notification_file(path, repo))
  298. return ret
  299. def _load_authentication_file(file, repo):
  300. debug(f'Loading { file }.')
  301. data = load_yaml(file)
  302. if not data:
  303. return []
  304. try:
  305. AUTHENTICATION_VALIDATOR.validate(data)
  306. except ValidationError:
  307. warn(f'Failed to validate { file } against the schema.', file)
  308. return []
  309. if 'id' in data:
  310. data['integration_type'] = 'authentication'
  311. data['_src_path'] = file
  312. data['_repo'] = repo
  313. data['_index'] = 0
  314. return [data]
  315. else:
  316. ret = []
  317. for idx, item in enumerate(data):
  318. item['integration_type'] = 'authentication'
  319. item['_src_path'] = file
  320. item['_repo'] = repo
  321. item['_index'] = idx
  322. ret.append(item)
  323. return ret
  324. def load_authentications():
  325. ret = []
  326. for repo, path, match in AUTHENTICATION_SOURCES:
  327. if match and path.exists() and path.is_dir():
  328. for file in path.glob(METADATA_PATTERN):
  329. ret.extend(_load_authentication_file(file, repo))
  330. elif not match and path.exists() and path.is_file():
  331. ret.extend(_load_authentication_file(path, repo))
  332. return ret
  333. def make_id(meta):
  334. if 'monitored_instance' in meta:
  335. instance_name = meta['monitored_instance']['name'].replace(' ', '_')
  336. elif 'instance_name' in meta:
  337. instance_name = meta['instance_name']
  338. else:
  339. instance_name = '000_unknown'
  340. return f'{ meta["plugin_name"] }-{ meta["module_name"] }-{ instance_name }'
  341. def make_edit_link(item):
  342. item_path = item['_src_path'].relative_to(REPO_PATH)
  343. return f'https://github.com/{ item["_repo"] }/blob/master/{ item_path }'
  344. def sort_integrations(integrations):
  345. integrations.sort(key=lambda i: i['_index'])
  346. integrations.sort(key=lambda i: i['_src_path'])
  347. integrations.sort(key=lambda i: i['id'])
  348. def dedupe_integrations(integrations, ids):
  349. tmp_integrations = []
  350. for i in integrations:
  351. if ids.get(i['id'], False):
  352. first_path, first_index = ids[i['id']]
  353. warn(f'Duplicate integration ID found at { i["_src_path"] } index { i["_index"] } (original definition at { first_path } index { first_index }), ignoring that integration.', i['_src_path'])
  354. else:
  355. tmp_integrations.append(i)
  356. ids[i['id']] = (i['_src_path'], i['_index'])
  357. return tmp_integrations, ids
  358. def render_collectors(categories, collectors, ids):
  359. debug('Computing default categories.')
  360. default_cats, valid_cats = get_category_sets(categories)
  361. debug('Generating collector IDs.')
  362. for item in collectors:
  363. item['id'] = make_id(item['meta'])
  364. debug('Sorting collectors.')
  365. sort_integrations(collectors)
  366. debug('Removing duplicate collectors.')
  367. collectors, ids = dedupe_integrations(collectors, ids)
  368. clean_collectors = []
  369. idmap = {i['id']: i for i in collectors}
  370. for item in collectors:
  371. debug(f'Processing { item["id"] }.')
  372. item['edit_link'] = make_edit_link(item)
  373. clean_item = deepcopy(item)
  374. related = []
  375. for res in item['meta']['related_resources']['integrations']['list']:
  376. res_id = make_id(res)
  377. if res_id not in idmap.keys():
  378. warn(f'Could not find related integration { res_id }, ignoring it.', item['_src_path'])
  379. continue
  380. related.append({
  381. 'plugin_name': res['plugin_name'],
  382. 'module_name': res['module_name'],
  383. 'id': res_id,
  384. 'name': idmap[res_id]['meta']['monitored_instance']['name'],
  385. 'info': idmap[res_id]['meta']['info_provided_to_referring_integrations'],
  386. })
  387. item_cats = set(item['meta']['monitored_instance']['categories'])
  388. bogus_cats = item_cats - valid_cats
  389. actual_cats = item_cats & valid_cats
  390. if bogus_cats:
  391. warn(f'Ignoring invalid categories: { ", ".join(bogus_cats) }', item["_src_path"])
  392. if not item_cats:
  393. item['meta']['monitored_instance']['categories'] = list(default_cats)
  394. warn(f'{ item["id"] } does not list any caregories, adding it to: { default_cats }', item["_src_path"])
  395. else:
  396. item['meta']['monitored_instance']['categories'] = [x for x in item['meta']['monitored_instance']['categories'] if x in list(actual_cats)]
  397. for scope in item['metrics']['scopes']:
  398. if scope['name'] == 'global':
  399. scope['name'] = f'{ item["meta"]["monitored_instance"]["name"] } instance'
  400. for cfg_example in item['setup']['configuration']['examples']['list']:
  401. if 'folding' not in cfg_example:
  402. cfg_example['folding'] = {
  403. 'enabled': item['setup']['configuration']['examples']['folding']['enabled']
  404. }
  405. for key in COLLECTOR_RENDER_KEYS:
  406. if key in item.keys():
  407. template = get_jinja_env().get_template(f'{ key }.md')
  408. data = template.render(entry=item, related=related, clean=False)
  409. clean_data = template.render(entry=item, related=related, clean=True)
  410. if 'variables' in item['meta']['monitored_instance']:
  411. template = get_jinja_env().from_string(data)
  412. data = template.render(variables=item['meta']['monitored_instance']['variables'])
  413. template = get_jinja_env().from_string(clean_data)
  414. clean_data = template.render(variables=item['meta']['monitored_instance']['variables'])
  415. else:
  416. data = ''
  417. clean_data = ''
  418. item[key] = data
  419. clean_item[key] = clean_data
  420. for k in ['_src_path', '_repo', '_index']:
  421. del item[k], clean_item[k]
  422. clean_collectors.append(clean_item)
  423. return collectors, clean_collectors, ids
  424. def render_deploy(distros, categories, deploy, ids):
  425. debug('Sorting deployments.')
  426. sort_integrations(deploy)
  427. debug('Checking deployment ids.')
  428. deploy, ids = dedupe_integrations(deploy, ids)
  429. clean_deploy = []
  430. template = get_jinja_env().get_template('platform_info.md')
  431. for item in deploy:
  432. debug(f'Processing { item["id"] }.')
  433. item['edit_link'] = make_edit_link(item)
  434. clean_item = deepcopy(item)
  435. if item['platform_info']['group']:
  436. entries = [
  437. {
  438. 'version': i['version'],
  439. 'support': i['support_type'],
  440. 'arches': i.get('packages', {'arches': []})['arches'],
  441. 'notes': i['notes'],
  442. } for i in distros[item['platform_info']['group']] if i['distro'] == item['platform_info']['distro']
  443. ]
  444. else:
  445. entries = []
  446. data = template.render(entries=entries, clean=False)
  447. clean_data = template.render(entries=entries, clean=True)
  448. for method in clean_item['methods']:
  449. for command in method['commands']:
  450. command['command'] = CUSTOM_TAG_PATTERN.sub('', command['command'])
  451. command['command'] = FIXUP_BLANK_PATTERN.sub('', command['command'])
  452. item['platform_info'] = data
  453. clean_item['platform_info'] = clean_data
  454. if 'clean_additional_info' in item:
  455. clean_item['additional_info'] = item['clean_additional_info']
  456. del item['clean_additional_info'], clean_item['clean_additional_info']
  457. for k in ['_src_path', '_repo', '_index']:
  458. del item[k], clean_item[k]
  459. clean_deploy.append(clean_item)
  460. return deploy, clean_deploy, ids
  461. def render_exporters(categories, exporters, ids):
  462. debug('Sorting exporters.')
  463. sort_integrations(exporters)
  464. debug('Checking exporter ids.')
  465. exporters, ids = dedupe_integrations(exporters, ids)
  466. clean_exporters = []
  467. for item in exporters:
  468. item['edit_link'] = make_edit_link(item)
  469. clean_item = deepcopy(item)
  470. for key in EXPORTER_RENDER_KEYS:
  471. if key in item.keys():
  472. template = get_jinja_env().get_template(f'{ key }.md')
  473. data = template.render(entry=item, clean=False)
  474. clean_data = template.render(entry=item, clean=True)
  475. if 'variables' in item['meta']:
  476. template = get_jinja_env().from_string(data)
  477. data = template.render(variables=item['meta']['variables'], clean=False)
  478. template = get_jinja_env().from_string(clean_data)
  479. clean_data = template.render(variables=item['meta']['variables'], clean=True)
  480. else:
  481. data = ''
  482. clean_data = ''
  483. item[key] = data
  484. clean_item[key] = clean_data
  485. for k in ['_src_path', '_repo', '_index']:
  486. del item[k], clean_item[k]
  487. clean_exporters.append(clean_item)
  488. return exporters, clean_exporters, ids
  489. def render_notifications(categories, notifications, ids):
  490. debug('Sorting notifications.')
  491. sort_integrations(notifications)
  492. debug('Checking notification ids.')
  493. notifications, ids = dedupe_integrations(notifications, ids)
  494. clean_notifications = []
  495. for item in notifications:
  496. item['edit_link'] = make_edit_link(item)
  497. clean_item = deepcopy(item)
  498. for key in NOTIFICATION_RENDER_KEYS:
  499. if key in item.keys():
  500. template = get_jinja_env().get_template(f'{ key }.md')
  501. data = template.render(entry=item, clean=False)
  502. clean_data = template.render(entry=item, clean=True)
  503. if 'variables' in item['meta']:
  504. template = get_jinja_env().from_string(data)
  505. data = template.render(variables=item['meta']['variables'], clean=False)
  506. template = get_jinja_env().from_string(clean_data)
  507. clean_data = template.render(variables=item['meta']['variables'], clean=True)
  508. else:
  509. data = ''
  510. clean_data = ''
  511. item[key] = data
  512. clean_item[key] = clean_data
  513. for k in ['_src_path', '_repo', '_index']:
  514. del item[k], clean_item[k]
  515. clean_notifications.append(clean_item)
  516. return notifications, clean_notifications, ids
  517. def render_authentications(categories, authentications, ids):
  518. debug('Sorting authentications.')
  519. sort_integrations(authentications)
  520. debug('Checking authentication ids.')
  521. authentications, ids = dedupe_integrations(authentications, ids)
  522. clean_authentications = []
  523. for item in authentications:
  524. item['edit_link'] = make_edit_link(item)
  525. clean_item = deepcopy(item)
  526. for key in AUTHENTICATION_RENDER_KEYS:
  527. if key in item.keys():
  528. template = get_jinja_env().get_template(f'{ key }.md')
  529. data = template.render(entry=item, clean=False)
  530. clean_data = template.render(entry=item, clean=True)
  531. if 'variables' in item['meta']:
  532. template = get_jinja_env().from_string(data)
  533. data = template.render(variables=item['meta']['variables'], clean=False)
  534. template = get_jinja_env().from_string(clean_data)
  535. clean_data = template.render(variables=item['meta']['variables'], clean=True)
  536. else:
  537. data = ''
  538. clean_data = ''
  539. item[key] = data
  540. clean_item[key] = clean_data
  541. for k in ['_src_path', '_repo', '_index']:
  542. del item[k], clean_item[k]
  543. clean_authentications.append(clean_item)
  544. return authentications, clean_authentications, ids
  545. def render_integrations(categories, integrations):
  546. template = get_jinja_env().get_template('integrations.js')
  547. data = template.render(
  548. categories=json.dumps(categories, indent=4),
  549. integrations=json.dumps(integrations, indent=4),
  550. )
  551. OUTPUT_PATH.write_text(data)
  552. def render_json(categories, integrations):
  553. JSON_PATH.write_text(json.dumps({
  554. 'categories': categories,
  555. 'integrations': integrations,
  556. }, indent=4))
  557. def main():
  558. categories = load_categories()
  559. distros = load_yaml(DISTROS_FILE)
  560. collectors = load_collectors()
  561. deploy = load_deploy()
  562. exporters = load_exporters()
  563. notifications = load_notifications()
  564. authentications = load_authentications()
  565. collectors, clean_collectors, ids = render_collectors(categories, collectors, dict())
  566. deploy, clean_deploy, ids = render_deploy(distros, categories, deploy, ids)
  567. exporters, clean_exporters, ids = render_exporters(categories, exporters, ids)
  568. notifications, clean_notifications, ids = render_notifications(categories, notifications, ids)
  569. authentications, clean_authentications, ids = render_authentications(categories, authentications, ids)
  570. integrations = collectors + deploy + exporters + notifications + authentications
  571. render_integrations(categories, integrations)
  572. clean_integrations = clean_collectors + clean_deploy + clean_exporters + clean_notifications + clean_authentications
  573. render_json(categories, clean_integrations)
  574. if __name__ == '__main__':
  575. sys.exit(main())