Skip to content

Commit e6b8409

Browse files
SCANPY-126 Serialize the scanner properties to JSON (#139)
1 parent 5fe8eb8 commit e6b8409

File tree

2 files changed

+166
-2
lines changed

2 files changed

+166
-2
lines changed

src/pysonar_scanner/configuration.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1919
#
2020
import time
21+
import json
2122
import argparse
2223
from dataclasses import dataclass
2324
from enum import Enum
24-
from typing import Optional
25+
from typing import Optional, Dict
2526

2627

2728
class JRECacheStatus(Enum):
@@ -89,6 +90,50 @@ class Sonar:
8990
class Configuration:
9091
sonar: Sonar = Sonar()
9192

93+
def __to_dict(self) -> Dict:
94+
scanner = self.sonar.scanner
95+
sonar = self.sonar
96+
97+
properties = [
98+
{"key": "sonar.scanner.app", "value": scanner.app},
99+
{"key": "sonar.scanner.appVersion", "value": scanner.app_version},
100+
{"key": "sonar.token", "value": sonar.token},
101+
]
102+
103+
optional_properties = [
104+
("sonar.region", sonar.region),
105+
("sonar.host.url", sonar.host_url),
106+
("sonar.projectBaseDir", sonar.project_base_dir),
107+
("sonar.verbose", sonar.verbose),
108+
("sonar.userHome", sonar.user_home),
109+
("sonar.scanner.apiBaseUrl", scanner.api_base_url),
110+
("sonar.scanner.bootstrapStartTime", scanner.bootstrap_start_time),
111+
("sonar.scanner.os", scanner.os),
112+
("sonar.scanner.arch", scanner.arch),
113+
("sonar.scanner.connectTimeout", scanner.connect_timeout),
114+
("sonar.scanner.socketTimeout", scanner.socket_timeout),
115+
("sonar.scanner.responseTimeout", scanner.response_timeout),
116+
("sonar.scanner.truststorePath", scanner.truststore_path),
117+
("sonar.scanner.truststorePassword", scanner.truststore_password),
118+
("sonar.scanner.keystorePath", scanner.keystore_path),
119+
("sonar.scanner.keystorePassword", scanner.keystore_password),
120+
("sonar.scanner.proxyHost", scanner.proxy_host),
121+
("sonar.scanner.proxyPort", scanner.proxy_port),
122+
("sonar.scanner.proxyUser", scanner.proxy_user),
123+
("sonar.scanner.proxyPassword", scanner.proxy_password),
124+
("sonar.scanner.wasJreCacheHit", scanner.was_jre_cache_hit.name if scanner.was_jre_cache_hit else None),
125+
("sonar.scanner.wasEngineCacheHit", scanner.was_engine_cache_hit),
126+
]
127+
128+
for key, value in optional_properties:
129+
if value is not None and value != "":
130+
properties.append({"key": key, "value": value})
131+
132+
return {"scannerProperties": properties}
133+
134+
def to_json(self) -> str:
135+
return json.dumps(self.__to_dict(), indent=2)
136+
92137

93138
class ConfigurationLoader:
94139

tests/test_configuration.py

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1919
#
2020
import unittest
21+
import json
22+
import time
2123

2224
from unittest.mock import patch
2325
from io import StringIO
2426

25-
from pysonar_scanner.configuration import ConfigurationLoader, Configuration, Scanner, Internal, Sonar
27+
from pysonar_scanner.configuration import ConfigurationLoader, Configuration, JRECacheStatus, Scanner, Internal, Sonar
2628

2729

2830
class TestMain(unittest.TestCase):
@@ -161,3 +163,120 @@ def test_all_cli_args(self):
161163

162164
expected_configuration = Configuration(sonar=expected_sonar)
163165
self.assertEqual(configuration, expected_configuration)
166+
167+
def test_minimal_json(self):
168+
minimal_json = Configuration(sonar=Sonar(token="MyToken")).to_json()
169+
170+
minimal_dict = json.loads(minimal_json)
171+
self.assertIn("scannerProperties", minimal_dict)
172+
self.assertIn("sonar.scanner.bootstrapStartTime", [prop["key"] for prop in minimal_dict["scannerProperties"]])
173+
bootstrap_start_time = [
174+
prop["value"]
175+
for prop in minimal_dict["scannerProperties"]
176+
if prop["key"] == "sonar.scanner.bootstrapStartTime"
177+
][0]
178+
self.assertAlmostEqual(
179+
bootstrap_start_time, int(time.time() * 1000), delta=1000 * 60
180+
) # 1 minute delta between the configuration creation and this test
181+
182+
expected_json = json.dumps(
183+
{
184+
"scannerProperties": [
185+
{"key": "sonar.scanner.app", "value": "python"},
186+
{"key": "sonar.scanner.appVersion", "value": "1.0"},
187+
{"key": "sonar.token", "value": "MyToken"},
188+
{"key": "sonar.verbose", "value": False},
189+
{"key": "sonar.scanner.bootstrapStartTime", "value": bootstrap_start_time},
190+
]
191+
}
192+
)
193+
expected_dict = json.loads(expected_json)
194+
self.assertDictEqual(minimal_dict, expected_dict)
195+
196+
def test_full_json(self):
197+
internal = Internal(
198+
dump_to_file="mySonarScannerInternalDumpToFile", sq_version="mySonarScannerInternalSqVersion"
199+
)
200+
201+
scanner = Scanner(
202+
internal=internal,
203+
os="windows",
204+
arch="x64",
205+
connect_timeout=42,
206+
socket_timeout=43,
207+
response_timeout=44,
208+
truststore_path="mySonarScannerTruststorePath",
209+
truststore_password="mySonarScannerTruststorePassword",
210+
keystore_path="mySonarScannerKeystorePath",
211+
keystore_password="mySonarScannerKeystorePassword",
212+
proxy_host="mySonarScannerProxyHost",
213+
proxy_port=45,
214+
proxy_user="mySonarScannerProxyUser",
215+
proxy_password="mySonarScannerProxyPassword",
216+
skip_jre_provisioning=True,
217+
java_exe_path="mySonarScannerJavaExePath",
218+
java_opts="mySonarScannerJavaOpts",
219+
sonarcloud_url="mySonarScannerCloudUrl",
220+
api_base_url="mySonarScannerApiUrl",
221+
was_engine_cache_hit=True,
222+
was_jre_cache_hit=JRECacheStatus.HIT,
223+
)
224+
225+
sonar = Sonar(
226+
scanner=scanner,
227+
token="MyToken",
228+
verbose=True,
229+
host_url="mySonarHostUrl",
230+
region="us",
231+
user_home="mySonarUserHome",
232+
project_base_dir="mySonarProjectBaseDir",
233+
)
234+
235+
full_configuration = Configuration(sonar=sonar)
236+
237+
full_json = full_configuration.to_json()
238+
full_dict = json.loads(full_json)
239+
self.assertIn("scannerProperties", full_dict)
240+
self.assertIn("sonar.scanner.bootstrapStartTime", [prop["key"] for prop in full_dict["scannerProperties"]])
241+
bootstrap_start_time = [
242+
prop["value"]
243+
for prop in full_dict["scannerProperties"]
244+
if prop["key"] == "sonar.scanner.bootstrapStartTime"
245+
][0]
246+
self.assertAlmostEqual(
247+
bootstrap_start_time, int(time.time() * 1000), delta=1000 * 60
248+
) # 1 minute delta between the configuration creation and this test
249+
250+
expected_json = json.dumps(
251+
{
252+
"scannerProperties": [
253+
{"key": "sonar.scanner.app", "value": "python"},
254+
{"key": "sonar.scanner.appVersion", "value": "1.0"},
255+
{"key": "sonar.token", "value": "MyToken"},
256+
{"key": "sonar.region", "value": "us"},
257+
{"key": "sonar.host.url", "value": "mySonarHostUrl"},
258+
{"key": "sonar.projectBaseDir", "value": "mySonarProjectBaseDir"},
259+
{"key": "sonar.verbose", "value": True},
260+
{"key": "sonar.userHome", "value": "mySonarUserHome"},
261+
{"key": "sonar.scanner.apiBaseUrl", "value": "mySonarScannerApiUrl"},
262+
{"key": "sonar.scanner.bootstrapStartTime", "value": bootstrap_start_time},
263+
{"key": "sonar.scanner.os", "value": "windows"},
264+
{"key": "sonar.scanner.arch", "value": "x64"},
265+
{"key": "sonar.scanner.connectTimeout", "value": 42},
266+
{"key": "sonar.scanner.socketTimeout", "value": 43},
267+
{"key": "sonar.scanner.responseTimeout", "value": 44},
268+
{"key": "sonar.scanner.truststorePath", "value": "mySonarScannerTruststorePath"},
269+
{"key": "sonar.scanner.truststorePassword", "value": "mySonarScannerTruststorePassword"},
270+
{"key": "sonar.scanner.keystorePath", "value": "mySonarScannerKeystorePath"},
271+
{"key": "sonar.scanner.keystorePassword", "value": "mySonarScannerKeystorePassword"},
272+
{"key": "sonar.scanner.proxyHost", "value": "mySonarScannerProxyHost"},
273+
{"key": "sonar.scanner.proxyPort", "value": 45},
274+
{"key": "sonar.scanner.proxyUser", "value": "mySonarScannerProxyUser"},
275+
{"key": "sonar.scanner.proxyPassword", "value": "mySonarScannerProxyPassword"},
276+
{"key": "sonar.scanner.wasJreCacheHit", "value": "HIT"},
277+
{"key": "sonar.scanner.wasEngineCacheHit", "value": True},
278+
]
279+
}
280+
)
281+
expected_dict = json.loads(expected_json)
282+
self.assertDictEqual(full_dict, expected_dict)

0 commit comments

Comments
 (0)