Skip to content

Commit 9d93933

Browse files
authored
isolate config parsing (DataDog#2321)
1 parent 581d6a2 commit 9d93933

File tree

4 files changed

+170
-144
lines changed

4 files changed

+170
-144
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# (C) Datadog, Inc. 2018
2+
# All rights reserved
3+
# Licensed under a 3-clause BSD style license (see LICENSE)
4+
from collections import namedtuple
5+
6+
from datadog_checks.config import _is_affirmative
7+
from datadog_checks.utils.headers import headers as agent_headers
8+
9+
10+
DEFAULT_EXPECTED_CODE = "(1|2|3)\d\d"
11+
12+
13+
Config = namedtuple('Config',
14+
'url, ntlm_domain, username, password, client_cert,'
15+
'client_key, method, data, http_response_status_code,'
16+
'timeout, include_content, headers, response_time,'
17+
'content_match, reverse_content_match, tags,'
18+
'disable_ssl_validation, ssl_expire, instance_ca_certs,'
19+
'weakcipher, check_hostname, ignore_ssl_warning,'
20+
'skip_proxy, allow_redirects')
21+
22+
23+
def from_instance(instance, default_ca_certs=None):
24+
"""
25+
Create a config object from an instance dictionary
26+
"""
27+
method = instance.get('method', 'get')
28+
data = instance.get('data', {})
29+
tags = instance.get('tags', [])
30+
ntlm_domain = instance.get('ntlm_domain')
31+
username = instance.get('username')
32+
password = instance.get('password')
33+
client_cert = instance.get('client_cert')
34+
client_key = instance.get('client_key')
35+
http_response_status_code = str(instance.get('http_response_status_code', DEFAULT_EXPECTED_CODE))
36+
timeout = int(instance.get('timeout', 10))
37+
config_headers = instance.get('headers', {})
38+
default_headers = _is_affirmative(instance.get("include_default_headers", True))
39+
if default_headers:
40+
headers = agent_headers({})
41+
else:
42+
headers = {}
43+
headers.update(config_headers)
44+
url = instance.get('url')
45+
content_match = instance.get('content_match')
46+
reverse_content_match = _is_affirmative(instance.get('reverse_content_match', False))
47+
response_time = _is_affirmative(instance.get('collect_response_time', True))
48+
if not url:
49+
raise Exception("Bad configuration. You must specify a url")
50+
include_content = _is_affirmative(instance.get('include_content', False))
51+
disable_ssl_validation = _is_affirmative(instance.get('disable_ssl_validation', True))
52+
ssl_expire = _is_affirmative(instance.get('check_certificate_expiration', True))
53+
instance_ca_certs = instance.get('ca_certs', default_ca_certs)
54+
weakcipher = _is_affirmative(instance.get('weakciphers', False))
55+
ignore_ssl_warning = _is_affirmative(instance.get('ignore_ssl_warning', False))
56+
check_hostname = _is_affirmative(instance.get('check_hostname', True))
57+
skip_proxy = _is_affirmative(
58+
instance.get('skip_proxy', instance.get('no_proxy', False)))
59+
allow_redirects = _is_affirmative(instance.get('allow_redirects', True))
60+
61+
return Config(url, ntlm_domain, username, password, client_cert, client_key,
62+
method, data, http_response_status_code, timeout,
63+
include_content, headers, response_time, content_match,
64+
reverse_content_match, tags, disable_ssl_validation,
65+
ssl_expire, instance_ca_certs, weakcipher, check_hostname,
66+
ignore_ssl_warning, skip_proxy, allow_redirects)

http_check/datadog_checks/http_check/http_check.py

+2-46
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,13 @@
1515
import requests
1616
from requests.packages.urllib3.exceptions import InsecureRequestWarning
1717
from requests_ntlm import HttpNtlmAuth
18-
1918
from datadog_checks.checks import NetworkCheck, Status
20-
from datadog_checks.config import _is_affirmative
21-
from datadog_checks.utils.headers import headers as agent_headers
2219

2320
from .adapters import WeakCiphersAdapter, WeakCiphersHTTPSConnection
2421
from .utils import get_ca_certs_path
22+
from .config import from_instance, DEFAULT_EXPECTED_CODE
2523

2624

27-
DEFAULT_EXPECTED_CODE = "(1|2|3)\d\d"
2825
DEFAULT_EXPIRE_DAYS_WARNING = 14
2926
DEFAULT_EXPIRE_DAYS_CRITICAL = 7
3027
DEFAULT_EXPIRE_WARNING = DEFAULT_EXPIRE_DAYS_WARNING * 24 * 3600
@@ -46,52 +43,11 @@ def __init__(self, name, init_config, agentConfig, instances=None):
4643
if not self.ca_certs:
4744
self.ca_certs = get_ca_certs_path()
4845

49-
def _load_conf(self, instance):
50-
# Fetches the conf
51-
method = instance.get('method', 'get')
52-
data = instance.get('data', {})
53-
tags = instance.get('tags', [])
54-
ntlm_domain = instance.get('ntlm_domain')
55-
username = instance.get('username')
56-
password = instance.get('password')
57-
client_cert = instance.get('client_cert')
58-
client_key = instance.get('client_key')
59-
http_response_status_code = str(instance.get('http_response_status_code', DEFAULT_EXPECTED_CODE))
60-
timeout = int(instance.get('timeout', 10))
61-
config_headers = instance.get('headers', {})
62-
default_headers = _is_affirmative(instance.get("include_default_headers", True))
63-
if default_headers:
64-
headers = agent_headers(self.agentConfig)
65-
else:
66-
headers = {}
67-
headers.update(config_headers)
68-
url = instance.get('url')
69-
content_match = instance.get('content_match')
70-
reverse_content_match = _is_affirmative(instance.get('reverse_content_match', False))
71-
response_time = _is_affirmative(instance.get('collect_response_time', True))
72-
if not url:
73-
raise Exception("Bad configuration. You must specify a url")
74-
include_content = _is_affirmative(instance.get('include_content', False))
75-
disable_ssl_validation = _is_affirmative(instance.get('disable_ssl_validation', True))
76-
ssl_expire = _is_affirmative(instance.get('check_certificate_expiration', True))
77-
instance_ca_certs = instance.get('ca_certs', self.ca_certs)
78-
weakcipher = _is_affirmative(instance.get('weakciphers', False))
79-
ignore_ssl_warning = _is_affirmative(instance.get('ignore_ssl_warning', False))
80-
check_hostname = _is_affirmative(instance.get('check_hostname', True))
81-
skip_proxy = _is_affirmative(
82-
instance.get('skip_proxy', instance.get('no_proxy', False)))
83-
allow_redirects = _is_affirmative(instance.get('allow_redirects', True))
84-
85-
return url, ntlm_domain, username, password, client_cert, client_key, method, data, http_response_status_code, \
86-
timeout, include_content, headers, response_time, content_match, reverse_content_match, tags, \
87-
disable_ssl_validation, ssl_expire, instance_ca_certs, weakcipher, check_hostname, ignore_ssl_warning, \
88-
skip_proxy, allow_redirects
89-
9046
def _check(self, instance):
9147
addr, ntlm_domain, username, password, client_cert, client_key, method, data, http_response_status_code, \
9248
timeout, include_content, headers, response_time, content_match, reverse_content_match, tags, \
9349
disable_ssl_validation, ssl_expire, instance_ca_certs, weakcipher, check_hostname, ignore_ssl_warning, \
94-
skip_proxy, allow_redirects = self._load_conf(instance)
50+
skip_proxy, allow_redirects = from_instance(instance, self.ca_certs)
9551

9652
start = time.time()
9753

http_check/tests/test_config.py

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# (C) Datadog, Inc. 2018
2+
# All rights reserved
3+
# Licensed under a 3-clause BSD style license (see LICENSE)
4+
import pytest
5+
6+
from datadog_checks.utils.headers import headers as agent_headers
7+
from datadog_checks.http_check.config import from_instance, DEFAULT_EXPECTED_CODE
8+
9+
10+
@pytest.mark.unit
11+
def test_from_instance():
12+
"""
13+
Test the defaults and the pieces of _load_conf that actually perform some logic
14+
"""
15+
# misconfiguration
16+
with pytest.raises(Exception) as e:
17+
from_instance({})
18+
assert 'Bad configuration' in str(e)
19+
20+
# defaults
21+
params = from_instance({
22+
'url': 'https://example.com',
23+
'name': 'UpService',
24+
})
25+
assert len(params) == 24
26+
27+
# `url` is mandatory
28+
assert params[0] == 'https://example.com'
29+
# default `ntlm_domain` is None
30+
assert params[1] is None
31+
# default `username` is None
32+
assert params[2] is None
33+
# default `password` is None
34+
assert params[3] is None
35+
# defualt `client_cert` is None
36+
assert params[4] is None
37+
# defualt `client_key` is None
38+
assert params[5] is None
39+
# default `method` is get
40+
assert params[6] == 'get'
41+
# default `data` is an empty dict
42+
assert params[7] == {}
43+
# default `http_response_status_code`
44+
assert params[8] == DEFAULT_EXPECTED_CODE
45+
# default `timeout` is 10
46+
assert params[9] == 10
47+
# default `include_content` is False
48+
assert params[10] is False
49+
# default headers
50+
assert params[11] == agent_headers({})
51+
# default `collect_response_time` is True
52+
assert params[12] is True
53+
# default `content_match` is None
54+
assert params[13] is None
55+
# default `reverse_content_match` is False
56+
assert params[14] is False
57+
# default `tags` is an empty list
58+
assert params[15] == []
59+
# default `disable_ssl_validation` is True
60+
assert params[16] is True
61+
# default `check_certificate_expiration` is True
62+
assert params[17] is True
63+
# default `ca_certs`, it's mocked we don't care
64+
assert params[18] != ''
65+
# default `weakciphers` is False
66+
assert params[19] is False
67+
# default `check_hostname` is True
68+
assert params[20] is True
69+
# default `ignore_ssl_warning` is False
70+
assert params[21] is False
71+
# default `skip_proxy` is False
72+
assert params[22] is False
73+
# default `allow_redirects` is True
74+
assert params[23] is True
75+
76+
# headers
77+
params = from_instance({
78+
'url': 'https://example.com',
79+
'name': 'UpService',
80+
'headers': {"X-Auth-Token": "SOME-AUTH-TOKEN"}
81+
})
82+
83+
headers = params[11]
84+
expected_headers = agent_headers({}).get('User-Agent')
85+
assert headers["X-Auth-Token"] == "SOME-AUTH-TOKEN", headers
86+
assert expected_headers == headers.get('User-Agent'), headers
87+
88+
# proxy
89+
params = from_instance({
90+
'url': 'https://example.com',
91+
'name': 'UpService',
92+
'no_proxy': True,
93+
})
94+
assert params[22] is True
95+
96+
params = from_instance({
97+
'url': 'https://example.com',
98+
'name': 'UpService',
99+
'no_proxy': False,
100+
'skip_proxy': True,
101+
})
102+
assert params[22] is True

http_check/tests/test_http_check.py

-98
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
import mock
1010

1111
from datadog_checks.http_check import HTTPCheck
12-
from datadog_checks.http_check.http_check import DEFAULT_EXPECTED_CODE
13-
from datadog_checks.utils.headers import headers as agent_headers
1412
from .common import (
1513
HERE, FAKE_CERT, CONFIG, CONFIG_SSL_ONLY, CONFIG_EXPIRED_SSL, CONFIG_CUSTOM_NAME,
1614
CONFIG_DATA_METHOD, CONFIG_HTTP_REDIRECTS, CONFIG_UNORMALIZED_INSTANCE_NAME,
@@ -38,102 +36,6 @@ def test__init__():
3836
assert http_check.ca_certs == 'foo'
3937

4038

41-
@pytest.mark.unit
42-
def test__load_conf(http_check):
43-
"""
44-
Test the defaults and the pieces of _load_conf that actually perform some logic
45-
"""
46-
# misconfiguration
47-
with pytest.raises(Exception) as e:
48-
http_check._load_conf({})
49-
assert 'Bad configuration' in str(e)
50-
51-
# defaults
52-
params = http_check._load_conf({
53-
'url': 'https://example.com',
54-
'name': 'UpService',
55-
})
56-
assert len(params) == 24
57-
58-
# `url` is mandatory
59-
assert params[0] == 'https://example.com'
60-
# default `ntlm_domain` is None
61-
assert params[1] is None
62-
# default `username` is None
63-
assert params[2] is None
64-
# default `password` is None
65-
assert params[3] is None
66-
# defualt `client_cert` is None
67-
assert params[4] is None
68-
# defualt `client_key` is None
69-
assert params[5] is None
70-
# default `method` is get
71-
assert params[6] == 'get'
72-
# default `data` is an empty dict
73-
assert params[7] == {}
74-
# default `http_response_status_code`
75-
assert params[8] == DEFAULT_EXPECTED_CODE
76-
# default `timeout` is 10
77-
assert params[9] == 10
78-
# default `include_content` is False
79-
assert params[10] is False
80-
# default headers
81-
assert params[11] == agent_headers({})
82-
# default `collect_response_time` is True
83-
assert params[12] is True
84-
# default `content_match` is None
85-
assert params[13] is None
86-
# default `reverse_content_match` is False
87-
assert params[14] is False
88-
# default `tags` is an empty list
89-
assert params[15] == []
90-
# default `disable_ssl_validation` is True
91-
assert params[16] is True
92-
# default `check_certificate_expiration` is True
93-
assert params[17] is True
94-
# default `ca_certs`, it's mocked we don't care
95-
assert params[18] != ''
96-
# default `weakciphers` is False
97-
assert params[19] is False
98-
# default `check_hostname` is True
99-
assert params[20] is True
100-
# default `ignore_ssl_warning` is False
101-
assert params[21] is False
102-
# default `skip_proxy` is False
103-
assert params[22] is False
104-
# default `allow_redirects` is True
105-
assert params[23] is True
106-
107-
# headers
108-
params = http_check._load_conf({
109-
'url': 'https://example.com',
110-
'name': 'UpService',
111-
'headers': {"X-Auth-Token": "SOME-AUTH-TOKEN"}
112-
})
113-
114-
headers = params[11]
115-
expected_headers = agent_headers({}).get('User-Agent')
116-
assert headers["X-Auth-Token"] == "SOME-AUTH-TOKEN", headers
117-
assert expected_headers == headers.get('User-Agent'), headers
118-
119-
# proxy
120-
params = http_check._load_conf({
121-
'url': 'https://example.com',
122-
'name': 'UpService',
123-
'no_proxy': True,
124-
})
125-
assert params[22] is True
126-
127-
params = http_check._load_conf({
128-
'url': 'https://example.com',
129-
'name': 'UpService',
130-
'no_proxy': False,
131-
'skip_proxy': True,
132-
})
133-
assert params[22] is True
134-
135-
136-
@pytest.mark.unit
13739
def test_check_cert_expiration(http_check):
13840
cert_path = os.path.join(HERE, 'fixtures', 'cacert.pem')
13941
check_hostname = True

0 commit comments

Comments
 (0)