Skip to content

Commit e91199c

Browse files
committed
feat: add atlassian-statuspage
1 parent 9704574 commit e91199c

File tree

16 files changed

+691
-5
lines changed

16 files changed

+691
-5
lines changed

CHANGELOG.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
1414

1515
Monitoring Plugins:
1616

17-
* about-me: reports type of display server (if any)
17+
* atlassian-statuspage: receive alerts on incidents on a specific Atlassian Statuspage
1818
* deb-updates: checks for software updates on systems that use package management systems based on the apt-get
1919
* kubectl-get-pods: checks the health and status of kubernetes pods by running `kubectl get pods` and parsing the results
20-
* redfish-sel: add support for Supermicro ([#866](https://github.com/Linuxfabrik/monitoring-plugins/issues/866))
21-
* systemd-unit: implement support for `systemctl --machine` and `--user`
22-
* snmp: add column "skip output" to CSV definition for devices, add unit tests
2320

2421

2522
### Fixed ("fix")
@@ -36,14 +33,15 @@ Monitoring Plugins:
3633
* snmp: Special characters not supported in options --v3-auth-prot-password and --v3-priv-prot-password ([#886](https://github.com/Linuxfabrik/monitoring-plugins/issues/886))
3734

3835

39-
### Changed ("refactor", "chore" etc.)
36+
### Changed ("feat", "refactor", "chore" etc.)
4037

4138
Build, CI/CD:
4239

4340
* create-fpms.sh: fix OS detection for setting OS family
4441

4542
Monitoring Plugins:
4643

44+
* about-me: reports type of display server (if any)
4745
* about-me: switch from lib.version to lib.distro
4846
* csv-values: make use of ommitted --warning-query and --critical-query more robust
4947
* disk-io: improve help text
@@ -55,8 +53,11 @@ Monitoring Plugins:
5553
* icinga-topflap-services: increase default warning level from 5 to 7
5654
* load: Use `os.getloadavg()` instead of `cat /proc/loadavg` ([#295](https://github.com/Linuxfabrik/monitoring-plugins/issues/295))
5755
* php-status: bz2 and curl are no default modules
56+
* redfish-sel: add support for Supermicro ([#866](https://github.com/Linuxfabrik/monitoring-plugins/issues/866))
5857
* rhel-version: switch from lib.version to lib.distro
58+
* snmp: add column "skip output" to CSV definition for devices, add unit tests
5959
* snmp: make table output suppressable, streamline output
60+
* systemd-unit: implement support for `systemctl --machine` and `--user`
6061

6162

6263

assets/icingaweb2-module-director/all-the-rest.json

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,12 @@
13151315
"entry_value": "Apache Solr",
13161316
"format": "string"
13171317
},
1318+
{
1319+
"allowed_roles": null,
1320+
"entry_name": "atlassian-statuspage",
1321+
"entry_value": "Atlassian Statuspage",
1322+
"format": "string"
1323+
},
13181324
{
13191325
"allowed_roles": null,
13201326
"entry_name": "axenita",
@@ -4438,6 +4444,58 @@
44384444
},
44394445
"uuid": "10a5a1ea-91fe-41c6-81e2-2f4b34c5e6ca"
44404446
},
4447+
"Atlassian Statuspage Service Set": {
4448+
"assign_filter": "\"atlassian-statuspage\"=host.vars.tags",
4449+
"description": null,
4450+
"object_name": "Atlassian Statuspage Service Set",
4451+
"object_type": "template",
4452+
"services": {
4453+
"Atlassian Statuspage": {
4454+
"action_url": null,
4455+
"apply_for": null,
4456+
"assign_filter": null,
4457+
"check_command": null,
4458+
"check_interval": null,
4459+
"check_period": null,
4460+
"check_timeout": null,
4461+
"command_endpoint": null,
4462+
"disabled": false,
4463+
"display_name": null,
4464+
"enable_active_checks": null,
4465+
"enable_event_handler": null,
4466+
"enable_flapping": null,
4467+
"enable_notifications": null,
4468+
"enable_passive_checks": null,
4469+
"enable_perfdata": null,
4470+
"event_command": null,
4471+
"fields": [],
4472+
"flapping_threshold_high": null,
4473+
"flapping_threshold_low": null,
4474+
"groups": [],
4475+
"host": null,
4476+
"icon_image": null,
4477+
"icon_image_alt": null,
4478+
"imports": [
4479+
"tpl-service-atlassian-statuspage"
4480+
],
4481+
"max_check_attempts": null,
4482+
"notes": null,
4483+
"notes_url": null,
4484+
"object_name": "Atlassian Statuspage",
4485+
"object_type": "object",
4486+
"retry_interval": null,
4487+
"service_set": null,
4488+
"template_choice": null,
4489+
"use_agent": null,
4490+
"use_var_overrides": null,
4491+
"uuid": "002a7013-3cbd-4518-80de-df753ee66870",
4492+
"vars": {},
4493+
"volatile": null,
4494+
"zone": null
4495+
}
4496+
},
4497+
"uuid": "052b37a8-7251-49b0-baf5-6955fc11c437"
4498+
},
44414499
"Axenita Service Set": {
44424500
"assign_filter": "\"axenita\"=host.vars.tags",
44434501
"description": null,
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
Check atlassian-statuspage
2+
==========================
3+
4+
Overview
5+
--------
6+
7+
Receive alerts on incidents on a specific `Atlassian Statuspage <https://www.atlassian.com/software/statuspage>`__. The plugin requires access to the `/api/v2/status.json` endpoint.
8+
9+
10+
Fact Sheet
11+
----------
12+
13+
.. csv-table::
14+
:widths: 30, 70
15+
16+
"Check Plugin Download", "https://github.com/Linuxfabrik/monitoring-plugins/tree/main/check-plugins/atlassian-statuspage"
17+
"Check Interval Recommendation", "Once a minute"
18+
"Can be called without parameters", "Yes"
19+
"Compiled for", "Linux"
20+
21+
22+
Help
23+
----
24+
25+
.. code-block:: text
26+
27+
usage: atlassian-statuspage [-h] [-V] [--always-ok] [--insecure] [--no-proxy]
28+
[--test TEST] [--timeout TIMEOUT] [--url URL]
29+
30+
Receive alerts on incidents on a specific Atlassian Statuspage.
31+
32+
options:
33+
-h, --help show this help message and exit
34+
-V, --version show program's version number and exit
35+
--always-ok Always returns OK.
36+
--insecure This option explicitly allows to perform "insecure" SSL
37+
connections. Default: False
38+
--no-proxy Do not use a proxy. Default: False
39+
--test TEST For unit tests. Needs "path-to-stdout-file,path-to-
40+
stderr-file,expected-retc".
41+
--timeout TIMEOUT Network timeout in seconds. Default: 8 (seconds)
42+
--url URL UptimeRobot Status Page URL. Default:
43+
https://status.atlassian.com
44+
45+
46+
Usage Examples
47+
--------------
48+
49+
.. code-block:: bash
50+
51+
./atlassian-statuspage --url=https://www.githubstatus.com
52+
53+
Output:
54+
55+
.. code-block:: text
56+
57+
Minor Service Outage @ https://www.githubstatus.com, last update at 2025-05-28T12:41:26 Etc/UTC (23m 11s ago)
58+
59+
60+
States
61+
------
62+
63+
See https://support.atlassian.com/statuspage/docs/top-level-status-and-incident-impact-calculations/:
64+
65+
* WARN if statuspage reports ['minor', 'maintenance']
66+
* CRIT if statuspage reports ['major', 'critical']
67+
68+
69+
Perfdata / Metrics
70+
------------------
71+
72+
.. csv-table::
73+
:widths: 25, 15, 60
74+
:header-rows: 1
75+
76+
Name, Type, Description
77+
impact, Number, "The current state (0 = OK, 1 = WARN, 2 = CRIT, 3 = UNKNOWN)."
78+
79+
80+
Credits, License
81+
----------------
82+
83+
* Authors: `Linuxfabrik GmbH, Zurich <https://www.linuxfabrik.ch>`_
84+
* License: The Unlicense, see `LICENSE file <https://unlicense.org/>`_.
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8; py-indent-offset: 4 -*-
3+
#
4+
# Author: Linuxfabrik GmbH, Zurich, Switzerland
5+
# Contact: info (at) linuxfabrik (dot) ch
6+
# https://www.linuxfabrik.ch/
7+
# License: The Unlicense, see LICENSE file.
8+
9+
# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.rst
10+
11+
"""See the check's README for more details.
12+
"""
13+
14+
import argparse # pylint: disable=C0413
15+
import json # pylint: disable=C0413
16+
import sys # pylint: disable=C0413
17+
18+
import lib.args # pylint: disable=C0413
19+
import lib.base # pylint: disable=C0413
20+
import lib.human # pylint: disable=C0413
21+
import lib.lftest # pylint: disable=C0413
22+
import lib.time # pylint: disable=C0413
23+
import lib.url # pylint: disable=C0413
24+
from lib.globals import (STATE_CRIT, STATE_OK, # pylint: disable=C0413
25+
STATE_UNKNOWN, STATE_WARN)
26+
27+
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
28+
__version__ = '2025052801'
29+
30+
DESCRIPTION = """Receive alerts on incidents on a specific Atlassian Statuspage."""
31+
32+
DEFAULT_INSECURE = False
33+
DEFAULT_NO_PROXY = False
34+
DEFAULT_TIMEOUT = 8
35+
DEFAULT_URL = 'https://status.atlassian.com'
36+
37+
38+
def parse_args():
39+
"""Parse command line arguments using argparse.
40+
"""
41+
parser = argparse.ArgumentParser(description=DESCRIPTION)
42+
43+
parser.add_argument(
44+
'-V', '--version',
45+
action='version',
46+
version=f'%(prog)s: v{__version__} by {__author__}'
47+
)
48+
49+
parser.add_argument(
50+
'--always-ok',
51+
help='Always returns OK.',
52+
dest='ALWAYS_OK',
53+
action='store_true',
54+
default=False,
55+
)
56+
57+
parser.add_argument(
58+
'--insecure',
59+
help='This option explicitly allows to perform "insecure" SSL connections. '
60+
'Default: %(default)s',
61+
dest='INSECURE',
62+
action='store_true',
63+
default=DEFAULT_INSECURE,
64+
)
65+
66+
parser.add_argument(
67+
'--no-proxy',
68+
help='Do not use a proxy. '
69+
'Default: %(default)s',
70+
dest='NO_PROXY',
71+
action='store_true',
72+
default=DEFAULT_NO_PROXY,
73+
)
74+
75+
parser.add_argument(
76+
'--test',
77+
help='For unit tests. Needs "path-to-stdout-file,path-to-stderr-file,expected-retc".',
78+
dest='TEST',
79+
type=lib.args.csv,
80+
)
81+
82+
parser.add_argument(
83+
'--timeout',
84+
help='Network timeout in seconds. '
85+
'Default: %(default)s (seconds)',
86+
dest='TIMEOUT',
87+
type=int,
88+
default=DEFAULT_TIMEOUT,
89+
)
90+
91+
parser.add_argument(
92+
'--url',
93+
help='Atlassian Statuspage URL. '
94+
'Default: %(default)s',
95+
dest='URL',
96+
default=DEFAULT_URL,
97+
)
98+
99+
return parser.parse_args()
100+
101+
102+
def statuspage2state(indicator):
103+
"""Convert Atlassian's Statuspage incident level to the Nagios world.
104+
https://support.atlassian.com/statuspage/docs/top-level-status-and-incident-impact-calculations/
105+
"""
106+
indicator = indicator.lower()
107+
if indicator in ['minor', 'maintenance']:
108+
return STATE_WARN
109+
if indicator in ['major', 'critical']:
110+
return STATE_CRIT
111+
# indicator == 'none'
112+
return STATE_OK
113+
114+
115+
def main():
116+
"""The main function. Hier spielt die Musik.
117+
"""
118+
119+
# parse the command line, exit with UNKNOWN if it fails
120+
try:
121+
args = parse_args()
122+
except SystemExit:
123+
sys.exit(STATE_UNKNOWN)
124+
125+
# fetch data (https://url/api/v2/status.json)
126+
if args.TEST is None:
127+
result = lib.base.coe(lib.url.fetch_json(
128+
f'{args.URL.rstrip("/")}/api/v2/status.json',
129+
insecure=args.INSECURE,
130+
no_proxy=args.NO_PROXY,
131+
timeout=args.TIMEOUT,
132+
))
133+
else:
134+
# do not call the command, put in test data
135+
result, _, _ = lib.lftest.test(args.TEST)
136+
result = json.loads(result)
137+
138+
# init some vars
139+
msg = ''
140+
state = statuspage2state(result.get('status').get('indicator'))
141+
perfdata = ''
142+
143+
# analyze data and build the message
144+
if state == STATE_OK:
145+
msg += f'Everything is ok @ {result.get("page").get("url")}'
146+
else:
147+
msg += f'{result.get("status").get("description")} @ {result.get("page").get("url")}, '
148+
updated_at = lib.time.timestr2epoch(
149+
result.get('page').get('updated_at')[:19], # 2025-05-28T11:04:36.171+01:00
150+
pattern='%Y-%m-%dT%H:%M:%S', # 2025-02-26T13:45:15
151+
tzinfo=lib.time.get_timezone(result.get('page').get('time_zone')),
152+
)
153+
delta = lib.time.now() - updated_at
154+
msg += f'last update at {result.get("page").get("updated_at")[:19]}'
155+
if result.get("page").get("time_zone"):
156+
msg += f' {result.get("page").get("time_zone")}'
157+
msg += f' ({lib.human.seconds2human(delta)} ago)'
158+
perfdata += lib.base.get_perfdata(
159+
'impact',
160+
state,
161+
uom=None,
162+
warn=None,
163+
crit=None,
164+
_min=STATE_OK,
165+
_max=STATE_UNKNOWN,
166+
)
167+
168+
# over and out
169+
lib.base.oao(msg, state, perfdata, always_ok=args.ALWAYS_OK)
170+
171+
172+
if __name__ == '__main__':
173+
try:
174+
main()
175+
except Exception: # pylint: disable=W0703
176+
lib.base.cu()

0 commit comments

Comments
 (0)