Skip to content

Commit 75725fc

Browse files
v-zhuravlevsatterly
authored andcommitted
better error handling when fetching remote config from Alerta API (#178)
1 parent a26d408 commit 75725fc

2 files changed

Lines changed: 121 additions & 2 deletions

File tree

alertaclient/config.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
1+
import json
22
import configparser
33
import os
44

55
import requests
66

7+
from alertaclient.exceptions import ClientException
8+
79
default_config = {
810
'config_file': '~/.alerta.conf',
911
'profile': None,
@@ -54,8 +56,11 @@ def get_remote_config(self, endpoint=None):
5456
config_url = '{}/config'.format(endpoint or self.options['endpoint'])
5557
try:
5658
r = requests.get(config_url, verify=self.options['sslverify'])
59+
r.raise_for_status()
5760
remote_config = r.json()
5861
except requests.RequestException as e:
59-
raise
62+
raise ClientException("Failed to get config from {}. Reason: {}".format(config_url, e))
63+
except json.decoder.JSONDecodeError:
64+
raise ClientException("Failed to get config from {}: Reason: not a JSON object".format(config_url))
6065

6166
self.options = {**remote_config, **self.options}

tests/test_remoteconfig.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
2+
import unittest
3+
import requests
4+
import requests_mock
5+
from requests_mock import Adapter
6+
from alertaclient.cli import Config
7+
from alertaclient.exceptions import ClientException
8+
9+
10+
class RemoteConfigTestCase(unittest.TestCase):
11+
12+
def setUp(self):
13+
self.adapter = Adapter()
14+
self.config = Config("")
15+
self.remote_json_config = """
16+
{
17+
"actions": [],
18+
"alarm_model": {
19+
"name": "Alerta 6.7.5"
20+
},
21+
"audio": {
22+
"new": null
23+
},
24+
"auth_required": false,
25+
"azure_tenant": null,
26+
"client_id": null,
27+
"colors": {
28+
"highlight": "skyblue ",
29+
"severity": {
30+
"cleared": "#00CC00",
31+
"critical": "red",
32+
"debug": "#9D006D",
33+
"indeterminate": "lightblue",
34+
"informational": "#00CC00",
35+
"major": "orange",
36+
"minor": "yellow",
37+
"normal": "#00CC00",
38+
"ok": "#00CC00",
39+
"security": "blue",
40+
"trace": "#7554BF",
41+
"unknown": "silver",
42+
"warning": "dodgerblue"
43+
},
44+
"text": "black"
45+
},
46+
"columns": ["severity", "status", "lastReceiveTime",
47+
"duplicateCount",
48+
"customer", "environment", "service", "resource",
49+
"event", "value", "text"],
50+
"customer_views": false,
51+
"dates": {
52+
"longDate": "d/M/yyyy h:mm:ss.sss a",
53+
"mediumDate": "EEE d MMM HH:mm",
54+
"shortTime": "HH:mm"
55+
},
56+
"email_verification": false,
57+
"endpoint": "http://localhost:8080/api",
58+
"github_url": "https://github.com",
59+
"gitlab_url": "https://gitlab.com",
60+
"keycloak_realm": null,
61+
"keycloak_url": null,
62+
"pingfederate_url": null,
63+
"provider": "basic",
64+
"refresh_interval": 5000,
65+
"severity": {
66+
"cleared": 5,
67+
"critical": 1,
68+
"debug": 7,
69+
"indeterminate": 5,
70+
"informational": 6,
71+
"major": 2,
72+
"minor": 3,
73+
"normal": 5,
74+
"ok": 5,
75+
"security": 0,
76+
"trace": 8,
77+
"unknown": 9,
78+
"warning": 4
79+
},
80+
"signup_enabled": true,
81+
"site_logo_url": "",
82+
"sort_by": "lastReceiveTime",
83+
"tracking_id": null
84+
}
85+
"""
86+
87+
@requests_mock.mock()
88+
def test_config_success(self, m):
89+
"""Tests successful remote config fetch"""
90+
m.get('/api/config', text=self.remote_json_config, status_code=200)
91+
self.config.get_remote_config('http://localhost:8080/api')
92+
self.assertEqual(self.config.options['alarm_model']['name'], 'Alerta 6.7.5')
93+
94+
@requests_mock.mock()
95+
def test_config_timeout(self, m):
96+
m.get('/api/config', exc=requests.exceptions.ConnectTimeout)
97+
with self.assertRaises(ClientException):
98+
self.config.get_remote_config('http://localhost:8080/api')
99+
100+
@requests_mock.mock()
101+
def test_config_not_found(self, m):
102+
103+
m.get('/config', status_code=404)
104+
with self.assertRaises(ClientException):
105+
self.config.get_remote_config('http://localhost:8080')
106+
107+
@requests_mock.mock()
108+
def test_config_not_json(self, m):
109+
"""Tests that URL is accessible (HTTP 200)
110+
but there is no Alerta API config in JSON"""
111+
112+
m.get('/sometext/config', text="Some random text", status_code=200)
113+
with self.assertRaises(ClientException):
114+
self.config.get_remote_config('http://localhost:8080/sometext')

0 commit comments

Comments
 (0)