Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit 1775bc2

Browse files
authored
Feature/tests (#45)
* tests for Containers * new tests for DockerHelper * next helpers tests * new test cases
1 parent 1324991 commit 1775bc2

File tree

5 files changed

+102
-6
lines changed

5 files changed

+102
-6
lines changed

docker_enforcer.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from base64 import b64decode
88
from logging import StreamHandler
99

10+
from docker import APIClient
1011
from flask import Flask, Response, request
1112
from pygments import highlight
1213
from pygments.formatters.html import HtmlFormatter
@@ -24,7 +25,8 @@
2425
from whitelist_rules.whitelist_rules import whitelist_rules
2526

2627
config = Config()
27-
docker_helper = DockerHelper(config)
28+
client: APIClient = APIClient(base_url=config.docker_socket, timeout=config.docker_req_timeout_sec)
29+
docker_helper = DockerHelper(config, client)
2830
judge = Judge(rules, "container", config, run_whitelists=True, custom_whitelist_rules=whitelist_rules)
2931
requests_judge = Judge(request_rules, "request", config, run_whitelists=False)
3032
jurek = Killer(docker_helper, config.mode)

dockerenforcer/docker_helper.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ def __str__(self, *args, **kwargs) -> str:
3838

3939

4040
class DockerHelper:
41-
def __init__(self, config: Config) -> None:
41+
def __init__(self, config: Config, client: APIClient) -> None:
4242
super().__init__()
4343
self._padlock = threading.Lock()
4444
self._check_in_progress: bool = False
4545
self._config: Config = config
46-
self._client: APIClient = APIClient(base_url=config.docker_socket, timeout=config.docker_req_timeout_sec)
46+
self._client: APIClient = client
4747
self._params_cache: Dict[str, Any] = {}
4848
self.last_check_containers_run_end_timestamp: datetime.datetime = datetime.datetime.min
4949
self.last_check_containers_run_start_timestamp: datetime.datetime = datetime.datetime.min
@@ -142,6 +142,7 @@ def get_params(self, container_id: str) -> Optional[Dict[str, Any]]:
142142
logger.error("Unexpected error when fetching params for container {0}: {1}".format(container_id, e))
143143
return {}
144144
logger.debug("[{0}] Params fetched for {1}".format(threading.current_thread().name, container_id))
145+
145146
if not self._config.cache_params:
146147
return params
147148

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# docker enforcer
2-
[![Build Status](https://travis-ci.org/piontec/docker-enforcer.png?branch=develop)](https://travis-ci.org/piontec/docker-enforcer)
3-
[![Coverage Status](https://coveralls.io/repos/github/piontec/docker-enforcer/badge.svg?branch=develop)](https://coveralls.io/github/piontec/docker-enforcer?branch=develop)
2+
[![Build Status](https://travis-ci.org/piontec/docker-enforcer.png?branch=feature/tests)](https://travis-ci.org/piontec/docker-enforcer)
3+
[![Coverage Status](https://coveralls.io/repos/github/piontec/docker-enforcer/badge.svg?branch=feature/tests)](https://coveralls.io/github/piontec/docker-enforcer?branch=feature/tests)
44

55
## Why?
66
Docker enforcer audits containers running on a shared docker host. The aim of docker enforcer is to

test/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class ApiContainerTest(unittest.TestCase):
1515
mem_rule = {"name": "must have memory limit", "rule": lambda c: c.params['HostConfig']['Memory'] == 0}
1616
cp_request_rule_regexp = re.compile("^/v1\.[23]\d/containers/test/archive$")
1717
cp_request_rule = {"name": "cp not allowed", "rule": lambda r, x=cp_request_rule_regexp:
18-
r['RequestMethod'] in ['GET', 'HEAD'] and x.match(r['ParsedUri'].path)}
18+
r['RequestMethod'] in ['GET', 'HEAD'] and x.match(r['ParsedUri'].path)}
1919
test_trigger_flag = False
2020
test_trigger = {"name": "set local flag", "trigger": lambda v: ApiContainerTest.set_trigger_flag()}
2121
forbid_privileged_rule = {

test/test_docker_helpers.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import unittest
2+
from unittest.mock import create_autospec
3+
4+
import docker
5+
6+
from dockerenforcer.config import Config
7+
from dockerenforcer.docker_helper import Container, CheckSource, DockerHelper
8+
9+
10+
class ContainerTests(unittest.TestCase):
11+
def test_create_without_name(self):
12+
container = Container("123", {"param1": 1}, {"cpu": 7}, 0, CheckSource.Periodic)
13+
self.assertEqual("123", str(container))
14+
15+
def test_create_with_name(self):
16+
container = Container("123", {"Name": "container1"}, {"cpu": 7}, 0, CheckSource.Periodic)
17+
self.assertEqual("container1", str(container))
18+
19+
20+
class DockerHelperTests(unittest.TestCase):
21+
def setUp(self):
22+
self._config = Config()
23+
self._client = create_autospec(docker.APIClient)
24+
self._helper = DockerHelper(self._config, self._client)
25+
self._cid = "cont_id1"
26+
self._cid2 = "cont_id2"
27+
self._params = {"Id": self._cid, "param1": "1"}
28+
self._params2 = {"Id": self._cid2, "param1": "2"}
29+
30+
def test_kill_container(self):
31+
c = Container(self._cid, params=self._params, metrics={}, position=0, check_source=CheckSource.Periodic)
32+
self._helper.kill_container(c)
33+
self._client.stop.assert_called_once_with(self._cid)
34+
35+
def test_get_params_no_cache(self):
36+
self._client.inspect_container.return_value = self._params
37+
params = self._helper.get_params(self._cid)
38+
self._client.inspect_container.assert_called_once_with(self._cid)
39+
self.assertDictEqual(params, self._params)
40+
41+
def test_get_params_fill_cache(self):
42+
self._config.cache_params = True
43+
self._client.inspect_container.return_value = self._params
44+
params = self._helper.get_params(self._cid)
45+
self._client.inspect_container.assert_called_once_with(self._cid)
46+
self.assertDictEqual(params, self._params)
47+
self.assertDictEqual(self._helper._params_cache[self._cid], self._params)
48+
49+
def test_get_params_from_cache_and_remove(self):
50+
self._config.cache_params = True
51+
self._helper._params_cache[self._cid] = self._params
52+
params = self._helper.get_params(self._cid)
53+
self._client.inspect_container.assert_not_called()
54+
self.assertDictEqual(params, self._params)
55+
self.assertDictEqual(self._helper._params_cache[self._cid], self._params)
56+
# now try to remove cached params
57+
self._helper.remove_from_cache(self._cid)
58+
self.assertFalse(self._cid in self._helper._params_cache)
59+
60+
def test_purge_cache(self):
61+
self._config.cache_params = True
62+
self._helper._params_cache[self._cid] = self._params
63+
self._helper._params_cache[self._cid2] = self._params2
64+
self._client.inspect_container.assert_not_called()
65+
self._helper.purge_cache([self._cid])
66+
self.assertFalse(self._cid2 in self._helper._params_cache)
67+
68+
def test_check_containers(self):
69+
self._config.disable_metrics = True
70+
self._client.containers.return_value = [{'Id': self._cid}, {'Id': self._cid2}]
71+
self._client.inspect_container.side_effect = [self._params, self._params2]
72+
containers = list(self._helper.check_containers(CheckSource.Periodic))
73+
self._client.containers.assert_called_once_with(quiet=True)
74+
self._client.inspect_container.side_effect = [self._params, self._params2]
75+
self.assertEqual(len(containers), 2)
76+
self.assertEqual(containers[0].cid, self._cid)
77+
self.assertEqual(containers[0].check_source, CheckSource.Periodic)
78+
self.assertDictEqual(containers[0].params, self._params)
79+
self.assertEqual(containers[1].cid, self._cid2)
80+
self.assertEqual(containers[1].check_source, CheckSource.Periodic)
81+
self.assertDictEqual(containers[1].params, self._params2)
82+
83+
def test_get_events(self):
84+
res = [
85+
{u'from': u'image/with:tag', u'id': self._cid, u'status': u'start', u'time': 1423339459},
86+
{u'from': u'image/with:tag', u'id': self._cid2, u'status': u'start', u'time': 1423339459}
87+
]
88+
self._client.events.return_value = res
89+
events = list(self._helper.get_events_observable())
90+
self._client.events.assert_called_once_with(decode=True)
91+
self.assertEqual(len(events), 2)
92+
self.assertEqual(events[0]['id'], self._cid)
93+
self.assertEqual(events[1]['id'], self._cid2)

0 commit comments

Comments
 (0)