Skip to content

Commit 8ebe3e8

Browse files
committed
Introduce option to use the system cert store for TLS authentication.
Enhance configuration management by adding default options and loading logic for registries, catalogs, hosts, certs and timeout settings. Introduce platform configuration method and update documentation and test cases.
1 parent e39ae17 commit 8ebe3e8

File tree

7 files changed

+162
-52
lines changed

7 files changed

+162
-52
lines changed

dem/__main__.py

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ def main() -> None:
2525
# Load the configuration file
2626
dem.cli.main.platform.config_file.update()
2727

28+
# Configure the Development Platform
29+
dem.cli.main.platform.configure()
30+
2831
# Load the Dev Env descriptors
2932
dem.cli.main.platform.load_dev_envs()
3033

dem/core/data_management.py

+50-21
Original file line numberDiff line numberDiff line change
@@ -89,23 +89,25 @@ class ConfigFile(BaseJSON):
8989
def __init__(self) -> None:
9090
""" Init the class."""
9191
self._path = PurePath(self._config_dir + "/config.json")
92-
self._default_json = """{
93-
"registries": [
94-
{
95-
"name": "axem",
96-
"namespace": "axemsolutions",
97-
"url": "https://registry.hub.docker.com"
98-
}
99-
],
100-
"catalogs": [
101-
{
102-
"name": "axem",
103-
"url": "https://axemsolutions.io/dem/dev_env_org.json"
92+
self._default_options = {
93+
"registries": [
94+
{
95+
"name": "axem",
96+
"namespace": "axemsolutions",
97+
"url": "https://registry.hub.docker.com"
98+
}
99+
],
100+
"catalogs": [
101+
{
102+
"name": "axem",
103+
"url": "https://axemsolutions.io/dem/dev_env_org.json"
104+
}
105+
],
106+
"hosts": [],
107+
"http_request_timeout_s": 2,
108+
"use_native_system_cert_store": False
104109
}
105-
],
106-
"hosts": [],
107-
"http_request_timeout_s": 2
108-
}"""
110+
self._default_json = json.dumps(self._default_options, indent=4)
109111
super().__init__()
110112

111113
def update(self) -> None:
@@ -114,10 +116,37 @@ def update(self) -> None:
114116
except json.decoder.JSONDecodeError as e:
115117
raise DataStorageError(f"The config.json file is corrupted.\n{str(e)}") from e
116118

117-
self.registries: list[dict] = self.deserialized.get("registries", [])
118-
self.catalogs: list[dict] = self.deserialized.get("catalogs", [])
119-
self.hosts: list[dict] = self.deserialized.get("hosts", [])
119+
flush_needed = False
120+
121+
self.registries: list[dict] | None = self.deserialized.get("registries", None)
122+
if self.registries is None:
123+
self.deserialized["registries"] = self._default_options["registries"]
124+
self.registries = self._default_options["registries"]
125+
flush_needed = True
126+
127+
self.catalogs: list[dict] | None = self.deserialized.get("catalogs", None)
128+
if self.catalogs is None:
129+
self.deserialized["catalogs"] = self._default_options["catalogs"]
130+
self.catalogs = self._default_options["catalogs"]
131+
flush_needed = True
132+
133+
self.hosts: list[dict] | None = self.deserialized.get("hosts", None)
134+
if self.hosts is None:
135+
self.deserialized["hosts"] = self._default_options["hosts"]
136+
self.hosts = self._default_options["hosts"]
137+
flush_needed = True
138+
120139
self.http_request_timeout_s: float = self.deserialized.get("http_request_timeout_s", None)
121-
122140
if self.http_request_timeout_s is None:
123-
raise DataStorageError("The http_request_timeout_s is not set in the config.json file.")
141+
self.deserialized["http_request_timeout_s"] = self._default_options["http_request_timeout_s"]
142+
self.http_request_timeout_s = self._default_options["http_request_timeout_s"]
143+
flush_needed = True
144+
145+
self.use_native_system_cert_store: bool | None = self.deserialized.get("use_native_system_cert_store", None)
146+
if self.use_native_system_cert_store is None:
147+
self.deserialized["use_native_system_cert_store"] = self._default_options["use_native_system_cert_store"]
148+
self.use_native_system_cert_store = self._default_options["use_native_system_cert_store"]
149+
flush_needed = True
150+
151+
if flush_needed:
152+
self.flush()

dem/core/platform.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Repesents the Development Platform. The platform resources can be accessed through this interface.
22
"""
33

4-
import os
4+
import os, truststore
55
from typing import Any, Generator
66
from dem.core.core import Core
77
from dem.core.properties import __supported_dev_env_major_version__
@@ -45,6 +45,11 @@ def __init__(self) -> None:
4545
# Set this to true in the platform instance to get the tool image info from the registries
4646
self.get_tool_image_info_from_registries = False
4747

48+
def configure(self) -> None:
49+
""" Configure the Development Platform."""
50+
if self.config_file.use_native_system_cert_store:
51+
truststore.inject_into_ssl()
52+
4853
def load_dev_envs(self) -> None:
4954
""" Load the Development Environments from the dev_env.json file.
5055

docs/configuration.md

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
## registries
2+
3+
The `registries` section of the configuration file is used to define the registries that DEM will
4+
use to search for images.
5+
6+
**Default value:**
7+
8+
```json
9+
"registries": [
10+
{
11+
"name": "axem",
12+
"namespace": "axemsolutions",
13+
"url": "https://registry.hub.docker.com"
14+
}
15+
]
16+
```
17+
18+
!!! info
19+
The Registry Management commands can be used to manage the registries in the configuration file.
20+
21+
- [`add-reg`](commands.md#dem-add-reg-name-url-namespace): Add a new registry to the configuration file.
22+
- [`del-reg`](commands.md#dem-del-reg-name): Delete a registry from the configuration file.
23+
- [`list-reg`](commands.md#dem-list-reg): List the registries in the configuration file.
24+
25+
26+
## catalogs
27+
28+
The `catalogs` section of the configuration file is used to define the catalogs that DEM will use to
29+
search for Development Environment descriptors.
30+
31+
** Default value: **
32+
33+
```json
34+
"catalogs": [
35+
{
36+
"name": "axem",
37+
"url": "https://axemsolutions.io/dem/dev_env_org.json"
38+
}
39+
]
40+
```
41+
42+
!!! info
43+
The Catalog Management commands can be used to manage the catalogs in the configuration file.
44+
45+
- [`add-cat`](commands.md#dem-add-cat-name-url): Add a new catalog to the configuration file.
46+
- [`del-cat`](commands.md#dem-del-cat-name): Delete a catalog from the configuration file.
47+
- [`list-cat`](commands.md#dem-list-cat): List the catalogs in the configuration file.
48+
49+
## hosts
50+
51+
!!! warning
52+
Remote hosts are not yet supported in DEM.
53+
54+
The `hosts` section of the configuration file is used to define the hosts that DEM will use as
55+
remote execution environments.
56+
57+
**Default value:**
58+
59+
```json
60+
"hosts": []
61+
```
62+
63+
!!! info
64+
The Host Management commands can be used to manage the hosts in the configuration file.
65+
66+
- [`add-host`](commands.md#dem-add-host-name-url): Add a new host to the configuration file.
67+
- [`del-host`](commands.md#dem-del-host-name): Delete a host from the configuration file.
68+
- [`list-host`](commands.md#dem-list-host): List the hosts in the configuration file.
69+
70+
## http_request_timeout_s
71+
72+
The `http_request_timeout_s` section of the configuration file is used to define the timeout for
73+
HTTP requests in seconds.
74+
75+
**Default value:**
76+
77+
```json
78+
"http_request_timeout_s": 2
79+
```
80+
81+
## use_native_system_cert_store
82+
83+
The `use_native_system_cert_store` section of the configuration file is used to define whether
84+
the native system certificate store should be used for HTTPS requests or the default one provided
85+
by the `certifi` package.
86+
87+
**Default value:**
88+
89+
```json
90+
"use_native_system_cert_store": false
91+
```
92+
93+
!!! info
94+
If the TLS authentication fails, try setting this value to `true`.

mkdocs.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ nav:
9292
- 'index.md'
9393
- 'installation.md'
9494
- 'basics.md'
95+
- 'quickstart.md'
9596
- Commands:
9697
- 'DevEnv Management':
9798
- 'add-task': 'commands/#dem-add-task-dev_env_name-task_name-command'
@@ -125,6 +126,6 @@ nav:
125126
- 'add-host': 'commands/#dem-add-host-name-address'
126127
- 'del-host': 'commands/#dem-del-host-name'
127128
- 'list-host': 'commands/#dem-list-host'
128-
- 'quickstart.md'
129+
- 'configuration.md'
129130
- 'design.md'
130131
- Join us on Discord : 'https://discord.gg/3aHuJBNvrJ'

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ dem = "dem.__main__:main"
3030
python = "^3.10"
3131
docker = "^7.0.0"
3232
readchar = "^4.0.6"
33-
requests = "^2.31.0"
33+
requests = "2.31.0"
3434
rich = "^13.7.1"
3535
typer = "^0.12.2"
36+
truststore = "^0.10.0"
3637

3738
[tool.poetry.group.docs]
3839
optional = true

tests/core/test_data_management.py

+5-28
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,6 @@ def test_ConfigFile(mock_PurePath: MagicMock):
170170
test_path = "test_path"
171171
data_management.BaseJSON._config_dir = test_path
172172

173-
mock_registries = MagicMock()
174-
mock_catalogs = MagicMock()
175-
mock_hosts = MagicMock()
176-
177173
# Run unit under test
178174
local_dev_env_json = data_management.ConfigFile()
179175

@@ -194,13 +190,15 @@ def test_ConfigFile(mock_PurePath: MagicMock):
194190
}
195191
],
196192
"hosts": [],
197-
"http_request_timeout_s": 2
193+
"http_request_timeout_s": 2,
194+
"use_native_system_cert_store": false
198195
}"""
199196

200197
mock_PurePath.assert_called_once_with(test_path + "/config.json")
201198

199+
@patch.object(data_management.BaseJSON, "flush")
202200
@patch.object(data_management.BaseJSON, "update")
203-
def test_ConfigFile_update(mock_update: MagicMock) -> None:
201+
def test_ConfigFile_update(mock_update: MagicMock, mock_flush: MagicMock) -> None:
204202
# Test setup
205203
test_config_file = data_management.ConfigFile()
206204
test_registry = MagicMock()
@@ -224,28 +222,7 @@ def test_ConfigFile_update(mock_update: MagicMock) -> None:
224222
assert test_config_file.http_request_timeout_s == test_http_request_timeout_s
225223

226224
mock_update.assert_called_once()
227-
228-
@patch.object(data_management.BaseJSON, "update")
229-
def test_ConfigFile_update_missing_http_request_timeout_s(mock_update: MagicMock) -> None:
230-
# Test setup
231-
test_config_file = data_management.ConfigFile()
232-
test_registry = MagicMock()
233-
test_catalog = MagicMock()
234-
test_host = MagicMock()
235-
test_config_file.deserialized = {
236-
"registries": [test_registry],
237-
"catalogs": [test_catalog],
238-
"hosts": [test_host],
239-
}
240-
241-
with pytest.raises(data_management.DataStorageError) as e:
242-
# Run unit under test
243-
test_config_file.update()
244-
245-
# Check expectations
246-
assert "Invalid file: The http_request_timeout_s is not set in the config.json file." == str(e.value)
247-
248-
mock_update.assert_called_once()
225+
mock_flush.assert_called_once()
249226

250227
@patch.object(data_management.BaseJSON, "update")
251228
def test_ConfigFile_update_JSONDecodeError(mock_update: MagicMock) -> None:

0 commit comments

Comments
 (0)