Remove the overview section from cloud notif. integrations (#18754)
Co-authored-by: ilyam8 <ilya@netdata.cloud>
Fotis Voutsas committed
Oct 14, 2024 at 11:23 UTC
0ab7826301d458bb384494be93e362feebad931e
7 files changed
+338
-153
integrations/cloud-notifications/metadata.yaml
-42
@@ -11,9 +11,6 @@
11
- mobile-app
12
- phone
13
- personal-notifications
14
- overview:
15
- notification_description: "You can configure notification delivery to the Netdata Mobile Application from the Netdata Cloud UI."
16
- notification_limitations: ""
14
setup:
15
description: |
16
### Prerequisites
@@ -44,9 +41,6 @@
41
keywords:
42
- discord
43
- community
47
- overview:
48
- notification_description: "You can configure notification delivery to your Discord server from the Netdata Cloud UI."
49
- notification_limitations: ""
44
setup:
45
description: |
46
### Prerequisites
@@ -85,9 +79,6 @@
79
icon_filename: "pagerduty.png"
80
keywords:
81
- pagerduty
88
- overview:
89
- notification_description: "You can configure notification delivery to PagerDuty from the Netdata Cloud UI."
90
- notification_limitations: ""
82
setup:
83
description: |
84
### Prerequisites
@@ -127,9 +118,6 @@
118
icon_filename: "slack.png"
119
keywords:
120
- slack
130
- overview:
131
- notification_description: "You can configure notification delivery to Slack from the Netdata Cloud UI."
132
- notification_limitations: ""
121
setup:
122
description: |
123
### Prerequisites
@@ -175,9 +163,6 @@
163
keywords:
164
- opsgenie
165
- atlassian
178
- overview:
179
- notification_description: "You can configure notification delivery to Opsgenie from the Netdata Cloud UI."
180
- notification_limitations: ""
166
setup:
167
description: |
168
### Prerequisites
@@ -215,9 +200,6 @@
200
icon_filename: "mattermost.png"
201
keywords:
202
- mattermost
218
- overview:
219
- notification_description: "You can configure notification delivery to Mattermost from the Netdata Cloud UI."
220
- notification_limitations: ""
203
setup:
204
description: |
205
### Prerequisites
@@ -260,9 +242,6 @@
242
icon_filename: "rocketchat.png"
243
keywords:
244
- rocketchat
263
- overview:
264
- notification_description: "You can configure notification delivery to RocketChat from the Netdata Cloud UI."
265
- notification_limitations: ""
245
setup:
246
description: |
247
### Prerequisites
@@ -306,9 +285,6 @@
285
icon_filename: "awssns.png"
286
keywords:
287
- awssns
309
- overview:
310
- notification_description: "You can configure notification delivery to AWS SNS from the Netdata Cloud UI."
311
- notification_limitations: ""
288
setup:
289
description: |
290
### Prerequisites
@@ -351,9 +327,6 @@
327
keywords:
328
- microsoft
329
- teams
354
- overview:
355
- notification_description: "You can configure notification delivery to a Microsoft Teams channel from the Netdata Cloud UI."
356
- notification_limitations: ""
330
setup:
331
description: |
332
### Prerequisites
@@ -396,9 +369,6 @@
369
icon_filename: "telegram.svg"
370
keywords:
371
- Telegram
399
- overview:
400
- notification_description: "You can configure notification delivery to Telegram from the Netdata Cloud UI."
401
- notification_limitations: ""
372
setup:
373
description: |
374
### Prerequisites
@@ -441,9 +411,6 @@
411
icon_filename: "splunk-black.svg"
412
keywords:
413
- Splunk
444
- overview:
445
- notification_description: "You can configure notification delivery to Splunk from the Netdata Cloud UI."
446
- notification_limitations: ""
414
setup:
415
description: |
416
### Prerequisites
@@ -479,9 +446,6 @@
446
- VictorOps
447
- Splunk
448
- On-Call
482
- overview:
483
- notification_description: "You can configure notification delivery to Splunk On-Call/VictorOps from the Netdata Cloud UI."
484
- notification_limitations: ""
449
setup:
450
description: |
451
### Prerequisites
@@ -515,9 +479,6 @@
479
keywords:
480
- generic webhooks
481
- webhooks
518
- overview:
519
- notification_description: "You can configure notification delivery to a webhook using a predefined schema from the Netdata Cloud UI."
520
- notification_limitations: ""
482
setup:
483
description: |
484
### Prerequisites
@@ -765,9 +726,6 @@
726
icon_filename: "ilert.svg"
727
keywords:
728
- ilert
768
- overview:
769
- notification_description: "You can configure notification delivery to ilert from the Netdata Cloud UI."
770
- notification_limitations: ""
729
setup:
730
description: |
731
### Prerequisites
integrations/gen_docs_integrations.py
+90
-38
@@ -1,7 +1,7 @@
1
import json
2
+import re
3
import shutil
4
from pathlib import Path
4
-import re
5
6
# Dictionary responsible for making the symbolic links at the end of the script's run.
7
symlink_dict = {}
@@ -29,6 +29,7 @@ def cleanup():
29
if "integrations" in str(element) and not "metadata.yaml" in str(element):
30
shutil.rmtree(element)
31
32
+
33
def generate_category_from_name(category_fragment, category_array):
34
"""
35
Takes a category ID in splitted form ("." as delimiter) and the array of the categories, and returns the proper category name that Learn expects.
@@ -46,7 +47,7 @@ def generate_category_from_name(category_fragment, category_array):
47
try:
48
# print("equals")
49
# print(fragment, category_fragment[i+1])
49
- dummy_id = dummy_id + "." + category_fragment[i+1]
50
+ dummy_id = dummy_id + "." + category_fragment[i + 1]
51
# print(dummy_id)
52
except IndexError:
53
return category_name.split("/", 1)[1]
@@ -79,10 +80,10 @@ def add_custom_edit_url(markdown_string, meta_yaml_link, sidebar_label_string, m
80
if mode == 'default':
81
path_to_md_file = f'{meta_yaml_link.replace("/metadata.yaml", "")}/integrations/{clean_string(sidebar_label_string)}'
82
82
- elif mode == 'cloud-notifications':
83
+ elif mode == 'cloud-notification':
84
path_to_md_file = meta_yaml_link.replace("metadata.yaml", f'integrations/{clean_string(sidebar_label_string)}')
85
85
- elif mode == 'agent-notifications':
86
+ elif mode == 'agent-notification':
87
path_to_md_file = meta_yaml_link.replace("metadata.yaml", "README")
88
89
elif mode == 'cloud-authentication':
@@ -122,23 +123,29 @@ def read_integrations_js(path_to_file):
123
print("Exception", e)
124
125
125
-def create_overview(integration, filename):
126
+def create_overview(integration, filename, overview_key_name="overview"):
127
+ # empty overview_key_name to have only image on overview
128
+ if not overview_key_name:
129
+ return f"""# {integration['meta']['name']}
130
127
- split = re.split(r'(#.*\n)', integration['overview'], 1)
131
+<img src="https://netdata.cloud/img/{filename}" width="150"/>
132
+"""
133
+
134
+ split = re.split(r'(#.*\n)', integration[overview_key_name], 1)
135
136
first_overview_part = split[1]
137
rest_overview_part = split[2]
138
132
- if len(filename) > 0:
133
- return f"""{first_overview_part}
139
+ if not filename:
140
+ return f"""{first_overview_part}{rest_overview_part}
141
+"""
142
+
143
+ return f"""{first_overview_part}
144
145
<img src="https://netdata.cloud/img/{filename}" width="150"/>
146
147
{rest_overview_part}
148
"""
139
- else:
140
- return f"""{first_overview_part}{rest_overview_part}
141
-"""
149
150
151
def build_readme_from_integration(integration, mode=''):
@@ -150,7 +157,8 @@ def build_readme_from_integration(integration, mode=''):
157
meta_yaml = integration['edit_link'].replace("blob", "edit")
158
sidebar_label = integration['meta']['monitored_instance']['name']
159
learn_rel_path = generate_category_from_name(
153
- integration['meta']['monitored_instance']['categories'][0].split("."), categories).replace("Data Collection", "Collecting Metrics")
160
+ integration['meta']['monitored_instance']['categories'][0].split("."), categories).replace(
161
+ "Data Collection", "Collecting Metrics")
162
most_popular = integration['meta']['most_popular']
163
164
# build the markdown string
@@ -221,7 +229,7 @@ endmeta-->
229
print("Exception in exporter md construction", e, integration['id'])
230
231
# NOTIFICATIONS
224
- elif mode == 'notification':
232
+ elif mode == 'agent-notification':
233
try:
234
# initiate the variables for the notification method
235
meta_yaml = integration['edit_link'].replace("blob", "edit")
@@ -238,7 +246,7 @@ learn_rel_path: "{learn_rel_path.replace("notifications", "Alerts & Notification
246
message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE NOTIFICATION'S metadata.yaml FILE"
247
endmeta-->
248
241
-{create_overview(integration, integration['meta']['icon_filename'])}"""
249
+{create_overview(integration, integration['meta']['icon_filename'], "overview")}"""
250
251
if integration['setup']:
252
md += f"""
@@ -252,7 +260,39 @@ endmeta-->
260
261
except Exception as e:
262
print("Exception in notification md construction", e, integration['id'])
255
-
263
+
264
+ elif mode == 'cloud-notification':
265
+ try:
266
+ # initiate the variables for the notification method
267
+ meta_yaml = integration['edit_link'].replace("blob", "edit")
268
+ sidebar_label = integration['meta']['name']
269
+ learn_rel_path = generate_category_from_name(integration['meta']['categories'][0].split("."), categories)
270
+
271
+ # build the markdown string
272
+ md = \
273
+ f"""<!--startmeta
274
+meta_yaml: "{meta_yaml}"
275
+sidebar_label: "{sidebar_label}"
276
+learn_status: "Published"
277
+learn_rel_path: "{learn_rel_path.replace("notifications", "Alerts & Notifications/Notifications")}"
278
+message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE NOTIFICATION'S metadata.yaml FILE"
279
+endmeta-->
280
+
281
+{create_overview(integration, integration['meta']['icon_filename'], "")}"""
282
+
283
+ if integration['setup']:
284
+ md += f"""
285
+{integration['setup']}
286
+"""
287
+
288
+ if integration['troubleshooting']:
289
+ md += f"""
290
+{integration['troubleshooting']}
291
+"""
292
+
293
+ except Exception as e:
294
+ print("Exception in notification md construction", e, integration['id'])
295
+
296
# AUTHENTICATIONS
297
elif mode == 'authentication':
298
if True:
@@ -339,27 +379,35 @@ def write_to_file(path, md, meta_yaml, sidebar_label, community, mode='default')
379
except KeyError:
380
# We don't need to print something here.
381
pass
342
- elif mode == 'notification':
382
+ elif mode == 'cloud-notification':
383
344
- if "cloud-notifications" in path:
345
- # for cloud notifications we generate them near their metadata.yaml
346
- name = clean_string(integration['meta']['name'])
384
+ # for cloud notifications we generate them near their metadata.yaml
385
+ name = clean_string(integration['meta']['name'])
386
348
- if not Path(f'{path}/integrations').exists():
349
- Path(f'{path}/integrations').mkdir()
387
+ if not Path(f'{path}/integrations').exists():
388
+ Path(f'{path}/integrations').mkdir()
389
+
390
+ # proper_edit_name = meta_yaml.replace(
391
+ # "metadata.yaml", f'integrations/{clean_string(sidebar_label)}.md\"')
392
351
- # proper_edit_name = meta_yaml.replace(
352
- # "metadata.yaml", f'integrations/{clean_string(sidebar_label)}.md\"')
393
+ md = add_custom_edit_url(md, meta_yaml, sidebar_label, mode='cloud-notification')
394
354
- md = add_custom_edit_url(md, meta_yaml, sidebar_label, mode='cloud-notifications')
395
+ finalpath = f'{path}/integrations/{name}.md'
396
+
397
+ try:
398
+ clean_and_write(
399
+ md,
400
+ Path(finalpath)
401
+ )
402
+ except FileNotFoundError as e:
403
+ print("Exception in writing to file", e)
404
+ elif mode == 'agent-notification':
405
+ # add custom_edit_url as the md file, so we can have uniqueness in the ingest script
406
+ # afterwards the ingest will replace this metadata with meta_yaml
407
356
- finalpath = f'{path}/integrations/{name}.md'
357
- else:
358
- # add custom_edit_url as the md file, so we can have uniqueness in the ingest script
359
- # afterwards the ingest will replace this metadata with meta_yaml
360
- md = add_custom_edit_url(md, meta_yaml, sidebar_label, mode='agent-notifications')
408
+ md = add_custom_edit_url(md, meta_yaml, sidebar_label, mode='agent-notification')
409
362
- finalpath = f'{path}/README.md'
410
+ finalpath = f'{path}/README.md'
411
412
try:
413
clean_and_write(
@@ -383,7 +431,7 @@ def write_to_file(path, md, meta_yaml, sidebar_label, community, mode='default')
431
md = add_custom_edit_url(md, meta_yaml, sidebar_label, mode='cloud-authentication')
432
433
finalpath = f'{path}/integrations/{name}.md'
386
-
434
+
435
try:
436
clean_and_write(
437
md,
@@ -422,7 +470,6 @@ cleanup()
470
471
categories, integrations = read_integrations_js('integrations/integrations.js')
472
425
-
473
# Iterate through every integration
474
for integration in integrations:
475
@@ -442,20 +489,25 @@ for integration in integrations:
489
path = build_path(meta_yaml)
490
write_to_file(path, md, meta_yaml, sidebar_label, community)
491
445
- # kind of specific if clause, so we can avoid running excessive code in the go repo
446
- elif integration['integration_type'] == "notification":
492
+ elif integration['integration_type'] == "agent_notification":
493
+
494
+ meta_yaml, sidebar_label, learn_rel_path, md, community = build_readme_from_integration(
495
+ integration, mode='agent-notification')
496
+ path = build_path(meta_yaml)
497
+ write_to_file(path, md, meta_yaml, sidebar_label, community, mode='agent-notification')
498
+
499
+ elif integration['integration_type'] == "cloud_notification":
500
501
meta_yaml, sidebar_label, learn_rel_path, md, community = build_readme_from_integration(
449
- integration, mode='notification')
502
+ integration, mode='cloud-notification')
503
path = build_path(meta_yaml)
451
- write_to_file(path, md, meta_yaml, sidebar_label, community, mode='notification')
504
+ write_to_file(path, md, meta_yaml, sidebar_label, community, mode='cloud-notification')
505
506
elif integration['integration_type'] == "authentication":
507
508
meta_yaml, sidebar_label, learn_rel_path, md, community = build_readme_from_integration(
509
integration, mode='authentication')
510
path = build_path(meta_yaml)
458
- write_to_file(path, md, meta_yaml, sidebar_label, community, mode='authentication')
459
-
511
+ write_to_file(path, md, meta_yaml, sidebar_label, community, mode='authentication')
512
513
make_symlinks(symlink_dict)
integrations/gen_integrations.py
+163
-54
@@ -4,7 +4,6 @@ import json
4
import os
5
import re
6
import sys
7
-
7
from copy import deepcopy
8
from pathlib import Path
9
@@ -40,8 +39,11 @@ EXPORTER_SOURCES = [
39
(AGENT_REPO, REPO_PATH / 'src' / 'exporting', True),
40
]
41
43
-NOTIFICATION_SOURCES = [
42
+AGENT_NOTIFICATION_SOURCES = [
43
(AGENT_REPO, REPO_PATH / 'src' / 'health' / 'notifications', True),
44
+]
45
+
46
+CLOUD_NOTIFICATION_SOURCES = [
47
(AGENT_REPO, INTEGRATIONS_PATH / 'cloud-notifications' / 'metadata.yaml', False),
48
]
49
@@ -64,12 +66,17 @@ EXPORTER_RENDER_KEYS = [
66
'troubleshooting',
67
]
68
67
-NOTIFICATION_RENDER_KEYS = [
69
+AGENT_NOTIFICATION_RENDER_KEYS = [
70
'overview',
71
'setup',
72
'troubleshooting',
73
]
74
75
+CLOUD_NOTIFICATION_RENDER_KEYS = [
76
+ 'setup',
77
+ 'troubleshooting',
78
+]
79
+
80
AUTHENTICATION_RENDER_KEYS = [
81
'overview',
82
'setup',
@@ -85,18 +92,18 @@ DEBUG = os.environ.get('DEBUG', False)
92
93
def debug(msg):
94
if GITHUB_ACTIONS:
88
- print(f':debug:{ msg }')
95
+ print(f':debug:{msg}')
96
elif DEBUG:
90
- print(f'>>> { msg }')
97
+ print(f'>>> {msg}')
98
else:
99
pass
100
101
102
def warn(msg, path):
103
if GITHUB_ACTIONS:
97
- print(f':warning file={ path }:{ msg }')
104
+ print(f':warning file={path}:{msg}')
105
else:
99
- print(f'!!! WARNING:{ path }:{ msg }')
106
+ print(f'!!! WARNING:{path}:{msg}')
107
108
109
def retrieve_from_filesystem(uri):
@@ -122,8 +129,13 @@ EXPORTER_VALIDATOR = Draft7Validator(
129
registry=registry,
130
)
131
125
-NOTIFICATION_VALIDATOR = Draft7Validator(
126
- {'$ref': './notification.json#'},
132
+AGENT_NOTIFICATION_VALIDATOR = Draft7Validator(
133
+ {'$ref': './agent_notification.json#'},
134
+ registry=registry,
135
+)
136
+
137
+CLOUD_NOTIFICATION_VALIDATOR = Draft7Validator(
138
+ {'$ref': './cloud_notification.json#'},
139
registry=registry,
140
)
141
@@ -209,19 +221,19 @@ def load_yaml(src):
221
yaml = YAML(typ='safe')
222
223
if not src.is_file():
212
- warn(f'{ src } is not a file.', src)
224
+ warn(f'{src} is not a file.', src)
225
return False
226
227
try:
228
contents = src.read_text()
229
except (IOError, OSError):
218
- warn(f'Failed to read { src }.', src)
230
+ warn(f'Failed to read {src}.', src)
231
return False
232
233
try:
234
data = yaml.load(contents)
235
except YAMLError:
224
- warn(f'Failed to parse { src } as YAML.', src)
236
+ warn(f'Failed to parse {src} as YAML.', src)
237
return False
238
239
return data
@@ -236,7 +248,7 @@ def load_categories():
248
try:
249
CATEGORY_VALIDATOR.validate(categories)
250
except ValidationError:
239
- warn(f'Failed to validate { CATEGORIES_FILE } against the schema.', CATEGORIES_FILE)
251
+ warn(f'Failed to validate {CATEGORIES_FILE} against the schema.', CATEGORIES_FILE)
252
sys.exit(1)
253
254
return categories
@@ -248,7 +260,7 @@ def load_collectors():
260
entries = get_collector_metadata_entries()
261
262
for repo, path in entries:
251
- debug(f'Loading { path }.')
263
+ debug(f'Loading {path}.')
264
data = load_yaml(path)
265
266
if not data:
@@ -257,7 +269,7 @@ def load_collectors():
269
try:
270
COLLECTOR_VALIDATOR.validate(data)
271
except ValidationError:
260
- warn(f'Failed to validate { path } against the schema.', path)
272
+ warn(f'Failed to validate {path} against the schema.', path)
273
continue
274
275
for idx, item in enumerate(data['modules']):
@@ -273,7 +285,7 @@ def load_collectors():
285
286
def _load_deploy_file(file, repo):
287
ret = []
276
- debug(f'Loading { file }.')
288
+ debug(f'Loading {file}.')
289
data = load_yaml(file)
290
291
if not data:
@@ -282,7 +294,7 @@ def _load_deploy_file(file, repo):
294
try:
295
DEPLOY_VALIDATOR.validate(data)
296
except ValidationError:
285
- warn(f'Failed to validate { file } against the schema.', file)
297
+ warn(f'Failed to validate {file} against the schema.', file)
298
return []
299
300
for idx, item in enumerate(data):
@@ -309,7 +321,7 @@ def load_deploy():
321
322
323
def _load_exporter_file(file, repo):
312
- debug(f'Loading { file }.')
324
+ debug(f'Loading {file}.')
325
data = load_yaml(file)
326
327
if not data:
@@ -318,7 +330,7 @@ def _load_exporter_file(file, repo):
330
try:
331
EXPORTER_VALIDATOR.validate(data)
332
except ValidationError:
321
- warn(f'Failed to validate { file } against the schema.', file)
333
+ warn(f'Failed to validate {file} against the schema.', file)
334
return []
335
336
if 'id' in data:
@@ -354,21 +366,21 @@ def load_exporters():
366
return ret
367
368
357
-def _load_notification_file(file, repo):
358
- debug(f'Loading { file }.')
369
+def _load_agent_notification_file(file, repo):
370
+ debug(f'Loading {file}.')
371
data = load_yaml(file)
372
373
if not data:
374
return []
375
376
try:
365
- NOTIFICATION_VALIDATOR.validate(data)
377
+ AGENT_NOTIFICATION_VALIDATOR.validate(data)
378
except ValidationError:
367
- warn(f'Failed to validate { file } against the schema.', file)
379
+ warn(f'Failed to validate {file} against the schema.', file)
380
return []
381
382
if 'id' in data:
371
- data['integration_type'] = 'notification'
383
+ data['integration_type'] = 'agent_notification'
384
data['_src_path'] = file
385
data['_repo'] = repo
386
data['_index'] = 0
@@ -378,7 +390,7 @@ def _load_notification_file(file, repo):
390
ret = []
391
392
for idx, item in enumerate(data):
381
- item['integration_type'] = 'notification'
393
+ item['integration_type'] = 'agent_notification'
394
item['_src_path'] = file
395
item['_repo'] = repo
396
item['_index'] = idx
@@ -387,20 +399,67 @@ def _load_notification_file(file, repo):
399
return ret
400
401
390
-def load_notifications():
402
+def _load_cloud_notification_file(file, repo):
403
+ debug(f'Loading {file}.')
404
+ data = load_yaml(file)
405
+
406
+ if not data:
407
+ return []
408
+
409
+ try:
410
+ CLOUD_NOTIFICATION_VALIDATOR.validate(data)
411
+ except ValidationError:
412
+ warn(f'Failed to validate {file} against the schema.', file)
413
+ return []
414
+
415
+ if 'id' in data:
416
+ data['integration_type'] = 'cloud_notification'
417
+ data['_src_path'] = file
418
+ data['_repo'] = repo
419
+ data['_index'] = 0
420
+
421
+ return [data]
422
+ else:
423
+ ret = []
424
+
425
+ for idx, item in enumerate(data):
426
+ item['integration_type'] = 'cloud_notification'
427
+ item['_src_path'] = file
428
+ item['_repo'] = repo
429
+ item['_index'] = idx
430
+ ret.append(item)
431
+
432
+ return ret
433
+
434
+
435
+def load_agent_notifications():
436
+ ret = []
437
+
438
+ for repo, path, match in AGENT_NOTIFICATION_SOURCES:
439
+ if match and path.exists() and path.is_dir():
440
+ for file in path.glob(METADATA_PATTERN):
441
+ ret.extend(_load_agent_notification_file(file, repo))
442
+ elif not match and path.exists() and path.is_file():
443
+ ret.extend(_load_agent_notification_file(path, repo))
444
+
445
+ return ret
446
+
447
+
448
+def load_cloud_notifications():
449
ret = []
450
393
- for repo, path, match in NOTIFICATION_SOURCES:
451
+ for repo, path, match in CLOUD_NOTIFICATION_SOURCES:
452
if match and path.exists() and path.is_dir():
453
for file in path.glob(METADATA_PATTERN):
396
- ret.extend(_load_notification_file(file, repo))
454
+ ret.extend(_load_cloud_notification_file(file, repo))
455
elif not match and path.exists() and path.is_file():
398
- ret.extend(_load_notification_file(path, repo))
456
+ ret.extend(_load_cloud_notification_file(path, repo))
457
458
return ret
459
460
+
461
def _load_authentication_file(file, repo):
403
- debug(f'Loading { file }.')
462
+ debug(f'Loading {file}.')
463
data = load_yaml(file)
464
465
if not data:
@@ -409,7 +468,7 @@ def _load_authentication_file(file, repo):
468
try:
469
AUTHENTICATION_VALIDATOR.validate(data)
470
except ValidationError:
412
- warn(f'Failed to validate { file } against the schema.', file)
471
+ warn(f'Failed to validate {file} against the schema.', file)
472
return []
473
474
if 'id' in data:
@@ -453,13 +512,13 @@ def make_id(meta):
512
else:
513
instance_name = '000_unknown'
514
456
- return f'{ meta["plugin_name"] }-{ meta["module_name"] }-{ instance_name }'
515
+ return f'{meta["plugin_name"]}-{meta["module_name"]}-{instance_name}'
516
517
518
def make_edit_link(item):
519
item_path = item['_src_path'].relative_to(REPO_PATH)
520
462
- return f'https://github.com/{ item["_repo"] }/blob/master/{ item_path }'
521
+ return f'https://github.com/{item["_repo"]}/blob/master/{item_path}'
522
523
524
def sort_integrations(integrations):
@@ -474,7 +533,9 @@ def dedupe_integrations(integrations, ids):
533
for i in integrations:
534
if ids.get(i['id'], False):
535
first_path, first_index = ids[i['id']]
477
- 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'])
536
+ warn(
537
+ f'Duplicate integration ID found at {i["_src_path"]} index {i["_index"]} (original definition at {first_path} index {first_index}), ignoring that integration.',
538
+ i['_src_path'])
539
else:
540
tmp_integrations.append(i)
541
ids[i['id']] = (i['_src_path'], i['_index'])
@@ -504,7 +565,7 @@ def render_collectors(categories, collectors, ids):
565
idmap = {i['id']: i for i in collectors}
566
567
for item in collectors:
507
- debug(f'Processing { item["id"] }.')
568
+ debug(f'Processing {item["id"]}.')
569
570
item['edit_link'] = make_edit_link(item)
571
@@ -516,7 +577,7 @@ def render_collectors(categories, collectors, ids):
577
res_id = make_id(res)
578
579
if res_id not in idmap.keys():
519
- warn(f'Could not find related integration { res_id }, ignoring it.', item['_src_path'])
580
+ warn(f'Could not find related integration {res_id}, ignoring it.', item['_src_path'])
581
continue
582
583
related.append({
@@ -532,17 +593,19 @@ def render_collectors(categories, collectors, ids):
593
actual_cats = item_cats & valid_cats
594
595
if bogus_cats:
535
- warn(f'Ignoring invalid categories: { ", ".join(bogus_cats) }', item["_src_path"])
596
+ warn(f'Ignoring invalid categories: {", ".join(bogus_cats)}', item["_src_path"])
597
598
if not item_cats:
599
item['meta']['monitored_instance']['categories'] = list(default_cats)
539
- warn(f'{ item["id"] } does not list any caregories, adding it to: { default_cats }', item["_src_path"])
600
+ warn(f'{item["id"]} does not list any caregories, adding it to: {default_cats}', item["_src_path"])
601
else:
541
- item['meta']['monitored_instance']['categories'] = [x for x in item['meta']['monitored_instance']['categories'] if x in list(actual_cats)]
602
+ item['meta']['monitored_instance']['categories'] = [x for x in
603
+ item['meta']['monitored_instance']['categories'] if
604
+ x in list(actual_cats)]
605
606
for scope in item['metrics']['scopes']:
607
if scope['name'] == 'global':
545
- scope['name'] = f'{ item["meta"]["monitored_instance"]["name"] } instance'
608
+ scope['name'] = f'{item["meta"]["monitored_instance"]["name"]} instance'
609
610
for cfg_example in item['setup']['configuration']['examples']['list']:
611
if 'folding' not in cfg_example:
@@ -552,7 +615,7 @@ def render_collectors(categories, collectors, ids):
615
616
for key in COLLECTOR_RENDER_KEYS:
617
if key in item.keys():
555
- template = get_jinja_env().get_template(f'{ key }.md')
618
+ template = get_jinja_env().get_template(f'{key}.md')
619
data = template.render(entry=item, related=related, clean=False)
620
clean_data = template.render(entry=item, related=related, clean=True)
621
@@ -589,7 +652,7 @@ def render_deploy(distros, categories, deploy, ids):
652
template = get_jinja_env().get_template('platform_info.md')
653
654
for item in deploy:
592
- debug(f'Processing { item["id"] }.')
655
+ debug(f'Processing {item["id"]}.')
656
item['edit_link'] = make_edit_link(item)
657
clean_item = deepcopy(item)
658
@@ -646,7 +709,7 @@ def render_exporters(categories, exporters, ids):
709
710
for key in EXPORTER_RENDER_KEYS:
711
if key in item.keys():
649
- template = get_jinja_env().get_template(f'{ key }.md')
712
+ template = get_jinja_env().get_template(f'{key}.md')
713
data = template.render(entry=item, clean=False)
714
clean_data = template.render(entry=item, clean=True)
715
@@ -670,7 +733,7 @@ def render_exporters(categories, exporters, ids):
733
return exporters, clean_exporters, ids
734
735
673
-def render_notifications(categories, notifications, ids):
736
+def render_agent_notifications(categories, notifications, ids):
737
debug('Sorting notifications.')
738
739
sort_integrations(notifications)
@@ -686,9 +749,52 @@ def render_notifications(categories, notifications, ids):
749
750
clean_item = deepcopy(item)
751
689
- for key in NOTIFICATION_RENDER_KEYS:
752
+ for key in AGENT_NOTIFICATION_RENDER_KEYS:
753
if key in item.keys():
691
- template = get_jinja_env().get_template(f'{ key }.md')
754
+ template = get_jinja_env().get_template(f'{key}.md')
755
+ data = template.render(entry=item, clean=False)
756
+
757
+ clean_data = template.render(entry=item, clean=True)
758
+
759
+ if 'variables' in item['meta']:
760
+ template = get_jinja_env().from_string(data)
761
+ data = template.render(variables=item['meta']['variables'], clean=False)
762
+ template = get_jinja_env().from_string(clean_data)
763
+ clean_data = template.render(variables=item['meta']['variables'], clean=True)
764
+ else:
765
+ data = ''
766
+ clean_data = ''
767
+
768
+ item[key] = data
769
+ clean_item[key] = clean_data
770
+
771
+ for k in ['_src_path', '_repo', '_index']:
772
+ del item[k], clean_item[k]
773
+
774
+ clean_notifications.append(clean_item)
775
+
776
+ return notifications, clean_notifications, ids
777
+
778
+
779
+def render_cloud_notifications(categories, notifications, ids):
780
+ debug('Sorting notifications.')
781
+
782
+ sort_integrations(notifications)
783
+
784
+ debug('Checking notification ids.')
785
+
786
+ notifications, ids = dedupe_integrations(notifications, ids)
787
+
788
+ clean_notifications = []
789
+
790
+ for item in notifications:
791
+ item['edit_link'] = make_edit_link(item)
792
+
793
+ clean_item = deepcopy(item)
794
+
795
+ for key in CLOUD_NOTIFICATION_RENDER_KEYS:
796
+ if key in item.keys():
797
+ template = get_jinja_env().get_template(f'{key}.md')
798
data = template.render(entry=item, clean=False)
799
clean_data = template.render(entry=item, clean=True)
800
@@ -729,9 +835,9 @@ def render_authentications(categories, authentications, ids):
835
clean_item = deepcopy(item)
836
837
for key in AUTHENTICATION_RENDER_KEYS:
732
-
838
+
839
if key in item.keys():
734
- template = get_jinja_env().get_template(f'{ key }.md')
840
+ template = get_jinja_env().get_template(f'{key}.md')
841
data = template.render(entry=item, clean=False)
842
clean_data = template.render(entry=item, clean=True)
843
@@ -746,7 +852,7 @@ def render_authentications(categories, authentications, ids):
852
853
item[key] = data
854
clean_item[key] = clean_data
749
-
855
+
856
for k in ['_src_path', '_repo', '_index']:
857
del item[k], clean_item[k]
858
@@ -777,20 +883,23 @@ def main():
883
collectors = load_collectors()
884
deploy = load_deploy()
885
exporters = load_exporters()
780
- notifications = load_notifications()
886
+ agent_notifications = load_agent_notifications()
887
+ cloud_notifications = load_cloud_notifications()
888
authentications = load_authentications()
889
890
collectors, clean_collectors, ids = render_collectors(categories, collectors, dict())
891
deploy, clean_deploy, ids = render_deploy(distros, categories, deploy, ids)
892
exporters, clean_exporters, ids = render_exporters(categories, exporters, ids)
786
- notifications, clean_notifications, ids = render_notifications(categories, notifications, ids)
893
+ agent_notifications, clean_agent_notifications, ids = render_agent_notifications(categories, agent_notifications,
894
+ ids)
895
+ cloud_notifications, clean_cloud_notifications, ids = render_cloud_notifications(categories, cloud_notifications,
896
+ ids)
897
authentications, clean_authentications, ids = render_authentications(categories, authentications, ids)
898
789
-
790
- integrations = collectors + deploy + exporters + notifications + authentications
899
+ integrations = collectors + deploy + exporters + agent_notifications + cloud_notifications + authentications
900
render_integrations(categories, integrations)
901
793
- clean_integrations = clean_collectors + clean_deploy + clean_exporters + clean_notifications + clean_authentications
902
+ clean_integrations = clean_collectors + clean_deploy + clean_exporters + clean_agent_notifications + clean_cloud_notifications + clean_authentications
903
render_json(categories, clean_integrations)
904
905
integrations/schemas/agent_notification.json
renamed
+14
-14
@@ -46,20 +46,20 @@
46
]
47
},
48
"global_setup": {
49
- "type": "object",
50
- "description": "Flags that show which global setup sections are relevant for this notification method.",
51
- "properties": {
52
- "severity_filtering": {
53
- "type": "boolean"
54
- },
55
- "http_proxy": {
56
- "type": "boolean"
57
- }
49
+ "type": "object",
50
+ "description": "Flags that show which global setup sections are relevant for this notification method.",
51
+ "properties": {
52
+ "severity_filtering": {
53
+ "type": "boolean"
54
},
59
- "required": [
60
- "severity_filtering",
61
- "http_proxy"
62
- ]
55
+ "http_proxy": {
56
+ "type": "boolean"
57
+ }
58
+ },
59
+ "required": [
60
+ "severity_filtering",
61
+ "http_proxy"
62
+ ]
63
},
64
"setup": {
65
"oneOf": [
@@ -84,4 +84,4 @@
84
]
85
}
86
}
87
-}
87
+}
\ No newline at end of file
integrations/schemas/cloud_notification.json
new
+68
@@ -0,0 +1,68 @@
1
+{
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Netdata notification mechanism metadata.",
4
+ "oneOf": [
5
+ {
6
+ "$ref": "#/$defs/entry"
7
+ },
8
+ {
9
+ "type": "array",
10
+ "minLength": 1,
11
+ "items": {
12
+ "$ref": "#/$defs/entry"
13
+ }
14
+ }
15
+ ],
16
+ "$defs": {
17
+ "entry": {
18
+ "type": "object",
19
+ "description": "Data for a single notification method.",
20
+ "properties": {
21
+ "id": {
22
+ "$ref": "./shared.json#/$defs/id"
23
+ },
24
+ "meta": {
25
+ "$ref": "./shared.json#/$defs/instance"
26
+ },
27
+ "keywords": {
28
+ "$ref": "./shared.json#/$defs/keywords"
29
+ },
30
+ "global_setup": {
31
+ "type": "object",
32
+ "description": "Flags that show which global setup sections are relevant for this notification method.",
33
+ "properties": {
34
+ "severity_filtering": {
35
+ "type": "boolean"
36
+ },
37
+ "http_proxy": {
38
+ "type": "boolean"
39
+ }
40
+ },
41
+ "required": [
42
+ "severity_filtering",
43
+ "http_proxy"
44
+ ]
45
+ },
46
+ "setup": {
47
+ "oneOf": [
48
+ {
49
+ "$ref": "./shared.json#/$defs/short_setup"
50
+ },
51
+ {
52
+ "$ref": "./shared.json#/$defs/full_setup"
53
+ }
54
+ ]
55
+ },
56
+ "troubleshooting": {
57
+ "$ref": "./shared.json#/$defs/troubleshooting"
58
+ }
59
+ },
60
+ "required": [
61
+ "id",
62
+ "meta",
63
+ "keywords",
64
+ "setup"
65
+ ]
66
+ }
67
+ }
68
+}
\ No newline at end of file
integrations/templates/overview.md
+1
-1
@@ -2,7 +2,7 @@
2
[% include 'overview/collector.md' %]
3
[% elif entry.integration_type == 'exporter' %]
4
[% include 'overview/exporter.md' %]
5
-[% elif entry.integration_type == 'notification' %]
5
+[% elif entry.integration_type == 'agent_notification' %]
6
[% include 'overview/notification.md' %]
7
[% elif entry.integration_type == 'authentication' %]
8
[% include 'overview/authentication.md' %]
integrations/templates/troubleshooting.md
+2
-4
@@ -85,13 +85,12 @@ docker logs netdata 2>&1 | grep [[ entry.meta.module_name ]]
85
86
[% endif %]
87
[% endif %]
88
-[% elif entry.integration_type == 'notification' %]
89
-[% if 'cloud-notifications' in entry._src_path|string %]
88
+[% elif entry.integration_type == 'cloud_notification' %]
89
[% if entry.troubleshooting.problems.list %]
90
## Troubleshooting
91
92
[% endif %]
94
-[% else %]
93
+[% elif entry.integration_type == 'agent_notification' %]
94
## Troubleshooting
95
96
### Test Notification
@@ -114,7 +113,6 @@ export NETDATA_ALARM_NOTIFY_DEBUG=1
113
114
Note that this will test _all_ alert mechanisms for the selected role.
115
117
-[% endif %]
116
[% elif entry.integration_type == 'exporter' %]
117
[% if entry.troubleshooting.problems.list %]
118
## Troubleshooting