Skip to content

Commit 0ec4af3

Browse files
authored
mcache check supports IPv6 address (#19359)
* mcache check supports IPv6 address Signed-off-by: keisku <keisuke.umegaki@datadoghq.com> * ddev dep freeze --------- Signed-off-by: keisku <keisuke.umegaki@datadoghq.com>
1 parent a1583f3 commit 0ec4af3

File tree

7 files changed

+67
-2
lines changed

7 files changed

+67
-2
lines changed

agent_requirements.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pysmi==1.2.1
4747
pysnmp-mibs==0.1.6
4848
pysnmp==5.1.0
4949
pysocks==1.7.1
50-
python-binary-memcached==0.31.2; sys_platform != 'win32'
50+
python-binary-memcached==0.31.4; sys_platform != 'win32'
5151
python-dateutil==2.9.0.post0
5252
python3-gearman==0.1.0; sys_platform != 'win32'
5353
pyvmomi==8.0.3.0.1

mcache/changelog.d/19359.added

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support IPv6.

mcache/datadog_checks/mcache/mcache.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# Licensed under Simplified BSD License (see LICENSE)
44
from __future__ import division
55

6+
from ipaddress import IPv6Address
7+
68
import bmemcached
79

810
from datadog_checks.base import AgentCheck, ConfigurationError
@@ -175,6 +177,13 @@ def _get_metrics(self, client, tags, service_check_tags=None):
175177
except BadResponseError:
176178
raise
177179

180+
def _is_ipv6(self, address):
181+
try:
182+
IPv6Address(address)
183+
return True
184+
except ValueError:
185+
return False
186+
178187
def _get_optional_metrics(self, client, tags, options=None):
179188
for arg, metrics_args in self.OPTIONAL_STATS.items():
180189
if not options or options.get(arg, False):
@@ -257,6 +266,12 @@ def check(self, instance):
257266
if not server and not socket:
258267
raise InvalidConfigError('Either "url" or "socket" must be configured')
259268

269+
if self._is_ipv6(server):
270+
# When it is already enclosed, this code path is not executed.
271+
# bmemcached requires IPv6 addresses to be enclosed in brackets,
272+
# because we set port with IP address at the client initialization.
273+
server = "[{}]".format(server)
274+
260275
if socket:
261276
server = 'unix'
262277
port = socket

mcache/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ dynamic = [
3636

3737
[project.optional-dependencies]
3838
deps = [
39-
"python-binary-memcached==0.31.2; sys_platform != 'win32'",
39+
"python-binary-memcached==0.31.4; sys_platform != 'win32'",
4040
]
4141

4242
[project.urls]

mcache/tests/compose/docker-compose.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,20 @@ services:
1616
volumes:
1717
- ${HOST_SOCKET_DIR}:${DOCKER_SOCKET_DIR}
1818
command: memcached -S -s ${DOCKER_SOCKET_PATH} -a 777
19+
20+
memcached_ipv6:
21+
image: datadog/docker-library:memcached_SASL
22+
environment:
23+
USERNAME: testuser
24+
PASSWORD: testpass
25+
networks:
26+
ip6net:
27+
ipv6_address: 2001:db8::2
28+
command: "memcached -S -l::"
29+
30+
networks:
31+
ip6net:
32+
enable_ipv6: true
33+
ipam:
34+
config:
35+
- subnet: 2001:db8::/64

mcache/tests/conftest.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ def dd_environment(e2e_instance):
6565
yield e2e_instance
6666

6767

68+
@pytest.fixture(scope='session')
69+
def dd_environment_ipv6(instance_ipv6):
70+
with docker_run(
71+
os.path.join(HERE, 'compose', 'docker-compose.yaml'),
72+
service_name='memcached_ipv6',
73+
env_vars={'PWD': HERE},
74+
conditions=[WaitFor(connect_to_mcache, args=(['{}:{}'.format('[2001:db8::2]', PORT)], USERNAME, PASSWORD))],
75+
):
76+
yield instance_ipv6
77+
78+
6879
@pytest.fixture
6980
def client():
7081
return bmemcached.Client(["{}:{}".format(HOST, PORT)], USERNAME, PASSWORD)
@@ -93,3 +104,9 @@ def e2e_instance():
93104
@pytest.fixture
94105
def instance_socket():
95106
return {'socket': get_host_socket_path(), 'tags': ['foo:bar'], 'username': USERNAME, 'password': PASSWORD}
107+
108+
109+
@pytest.fixture(scope='session')
110+
def instance_ipv6():
111+
# This IPv6 address is defined in the docker-compose file.
112+
return {'url': '2001:db8::2', 'port': PORT, 'tags': ['foo:bar'], 'username': USERNAME, 'password': PASSWORD}

mcache/tests/test_integration_e2e.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,18 @@ def test_connections_leaks(check, instance):
154154
check.check(instance)
155155
# Verify that the count is still 0
156156
assert count_connections(PORT) == 0
157+
158+
159+
@pytest.mark.integration
160+
@pytest.mark.usefixtures('dd_environment_ipv6')
161+
def test_service_ok_ipv6(instance_ipv6, aggregator, dd_run_check):
162+
"""
163+
Service is up
164+
"""
165+
tags = ["host:[2001:db8::2]", "port:{}".format(PORT), "foo:bar"]
166+
check = Memcache('mcache', {}, [instance_ipv6])
167+
dd_run_check(check)
168+
assert len(aggregator.service_checks(SERVICE_CHECK)) == 1
169+
sc = aggregator.service_checks(SERVICE_CHECK)[0]
170+
assert sc.status == check.OK
171+
assert sc.tags == tags

0 commit comments

Comments
 (0)