Skip to content

Commit b0ca7a8

Browse files
committed
Implement configuration API of the TSP
It replaces the list/load/delete extension CLI that used the undocumented XML endpoint of Trace Compass server. It adds the following commands and corresponding TSP API calls: - --list-configuration-sources: list all the configuration source types - --list-configuration-sourceL list a single configuration source type - --list-configurations: list loaded configurations for a source type - --list-configuration: list a single configuration for a source type - --load-configuration: load a configuration for a source type - --update-configuration: update a configuration for a source type - --delete-configuration: delete a configuration for a source type Update README.md as well for these new commands. Signed-off-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
1 parent 245d994 commit b0ca7a8

11 files changed

+670
-73
lines changed

.vscode/launch.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,19 @@
55
"version": "0.2.0",
66
"configurations": [
77
{
8-
"name": "Python: Current File",
8+
"name": "Python: Test",
99
"type": "python",
1010
"request": "launch",
1111
"program": ".venv/bin/pytest",
1212
"console": "integratedTerminal"
13+
},
14+
{
15+
"name": "Python: CLI",
16+
"type": "python",
17+
"request": "launch",
18+
"program": "tsp_cli_client",
19+
"args": ["--list-experiments"],
20+
"console": "integratedTerminal"
1321
}
1422
]
1523
}

README.md

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,28 @@ To use the **tsp_cli_client** script, type the following command in the root dir
5959
```python
6060
./tsp_cli_client -h
6161

62-
usage: tsp_cli_client [-h] [--ip IP] [--port PORT] [--open-trace TRACE_PATH]
62+
usage: tsp_cli_client [-h] [--ip IP] [--port PORT]
63+
[--open-trace TRACE_PATH]
6364
[--name NAME] [--list-trace UUID] [--list-traces]
6465
[--delete-trace UUID] [--open-experiment EXP_NAME]
6566
[--list-experiment UUID] [--list-experiments]
6667
[--delete-experiment UUID] [--list-outputs UUID]
6768
[--list-output OUTPUT_ID] [--get-tree OUTPUT_ID]
69+
[--get-timegraph-tree OUTPUT_ID]
6870
[--get-xy-tree OUTPUT_ID] [--get-xy OUTPUT_ID]
6971
[--items [ITEMS ...]] [--times [TIMES ...]]
7072
[--uuid UUID] [--uuids [UUIDS ...]] [--do-delete-traces]
71-
[--paths [PATHS ...]] [--list-extensions]
72-
[--load-extension EXTENSION_PATH]
73-
[--delete-extension EXTENSION_NAME]
73+
[--paths [PATHS ...]]
74+
[--list-configuration-sources]
75+
[--list-configuration-source TYPE_ID]
76+
[--list-configurations TYPE_ID]
77+
[--list-configuration CONFIG_ID]
78+
[--load-configuration]
79+
[--update-configuration]
80+
[--delete-configuration CONFIGURATION_ID]
81+
[--type-id TYPE_ID]
82+
[--config-id CONFIG_ID]
83+
[--params PARAMS]
7484

7585
CLI client to send Trace Server Protocol commands to a Trace Server.
7686

@@ -94,21 +104,62 @@ optional arguments:
94104
--list-outputs UUID Get details on the given trace
95105
--list-output OUTPUT_ID
96106
Get details on the given output of a trace
97-
--get-tree OUTPUT_ID Get the timegraph tree of an output
107+
--get-tree OUTPUT_ID Get the tree of an output of type DATA_TREE
108+
--get-timegraph-tree OUTPUT_ID
109+
Get the tree of an output of type TIME_GRAPH
98110
--get-xy-tree OUTPUT_ID
99-
Get the XY tree of an output
111+
Get the tree of an output of type TREE_TIME_XY
100112
--get-xy OUTPUT_ID Get the XY data of an output
101113
--items [ITEMS ...] The list of XY items requested
102114
--times [TIMES ...] The list of XY times requested
103115
--uuid UUID The UUID of a trace
104116
--uuids [UUIDS ...] The list of UUIDs
105117
--do-delete-traces Also delete traces when deleting experiment
106118
--paths [PATHS ...] List of trace paths to be part of an experiment
107-
--list-extensions Get the extensions loaded
108-
--load-extension EXTENSION_PATH
109-
Load an extension
110-
--delete-extension EXTENSION_NAME
111-
Delete an extension
119+
--list-configuration-sources
120+
Get the available configuration sources
121+
--list-configuration-source TYPE_ID
122+
Get a available configuration source
123+
--list-configurations TYPE_ID
124+
Get the configurations loaded for given type
125+
--list-configuration CONFIG_ID
126+
Get a configuration loaded for given type and config id
127+
--load-configuration Load an configuration using paramemeters provided by --params
128+
--update-configuration
129+
Update an configuration using paramemeters provided by --params
130+
--delete-configuration CONFIGURATION_ID
131+
Delete a configuration
132+
--type-id TYPE_ID id of configuration source type
133+
--config-id CONFIG_ID
134+
id of configuration
135+
--params PARAMS comma separated key value pairs (key1=val1,key2=val2)
136+
```
137+
138+
Examples:
139+
```python
140+
'''Open trace '''
141+
./tsp_cli_client --open-trace TRACE_PATH [--name NAME]
142+
./tsp_cli_client --list-traces
143+
./tsp_cli_client --list-trace UUID
144+
./tsp_cli_client --list-trace UUID
145+
./tsp_cli_client --delete-trace UUID
146+
./tsp_cli_client --open-experiment EXP_NAME --uuids UUIDS
147+
./tsp_cli_client --open-experiment EXP_NAME --paths PATHS
148+
./tsp_cli_client --list-experiments
149+
./tsp_cli_client --list-experiment UUID
150+
./tsp_cli_client --delete-experiment UUID [--do-delete-traces]
151+
./tsp_cli_client --list-outputs UUID
152+
./tsp_cli_client --get-tree OUTPUT_ID --uuid UUID
153+
./tsp_cli_client --get-timegraph-tree OUTPUT_ID --uuid UUID
154+
./tsp_cli_client --get-xy-tree OUTPUT_ID --uuid UUID
155+
./tsp_cli_client --get-xy OUTPUT_ID --uuid UUID --items ITEMS --times TIMES
156+
./tsp_cli_client --list-configuration-sources
157+
./tsp_cli_client --list-configuration-source TYPE_ID
158+
./tsp_cli_client --list-configurations TYPE_ID
159+
./tsp_cli_client --list-configuration CONFIG_ID --type-id TYPE_ID
160+
./tsp_cli_client --load-configuration --type-id TYPE_ID --params key1:value1
161+
./tsp_cli_client --update-configuration --type-id TYPE_ID --config-id CONFIG_ID --params key1=value1,key2=value2
162+
./tsp_cli_client --delete-configuration CONFIGURATION_ID --type-id TYPE_ID
112163
```
113164

114165
[agc]: https://kislyuk.github.io/argcomplete/#activating-global-completion

test_tsp.py

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# The MIT License (MIT)
22
#
3-
# Copyright (C) 2021 - Ericsson
3+
# Copyright (C) 2021, 2023 - Ericsson
44
#
55
# Permission is hereby granted, free of charge, to any person obtaining a copy
66
# of this software and associated documentation files (the "Software"), to deal
@@ -43,6 +43,8 @@
4343
REQUESTED_TIME_START) / REQUESTED_TIME_LENGTH
4444

4545

46+
CONFIG_SOURCE_TYPE = 'org.eclipse.tracecompass.tmf.core.config.xmlsourcetype'
47+
4648
# pylint: disable=too-many-public-methods
4749
class TestTspClient:
4850
"""TspClient test methods.
@@ -405,31 +407,73 @@ def test_fetch_timegraph_tree_complete(self, kernel):
405407
self._delete_experiments()
406408
self._delete_traces()
407409

408-
def test_fetch_extensions_none(self):
409-
"""Expect no extensions without posting any."""
410-
response = self.tsp_client.fetch_extensions()
410+
def test_fetch_configuration_sources(self):
411+
"""Expect at least configuration source ."""
412+
response = self.tsp_client.fetch_configuration_sources()
413+
assert response.status_code == 200
414+
assert response.model.configuration_source_set
415+
416+
response = self.tsp_client.fetch_configuration_source(CONFIG_SOURCE_TYPE)
411417
assert response.status_code == 200
412-
assert not response.model.extension_set
418+
assert response.model
419+
420+
def test_fetch_configurations_none(self):
421+
"""Expect no configurations without posting any."""
422+
response = self.tsp_client.fetch_configurations(CONFIG_SOURCE_TYPE)
423+
assert response.status_code == 200
424+
assert response.model.configuration_set
425+
426+
response = self.tsp_client.fetch_configuration(CONFIG_SOURCE_TYPE, self.name)
427+
assert response.status_code == 404
413428

414-
def test_post_extension(self, extension):
415-
"""Expect extension after posting it."""
416-
response = self.tsp_client.post_extension(extension)
429+
def test_post_configuration(self, extension):
430+
"""Expect configuration after posting it."""
431+
params = {}
432+
params['path'] = extension
433+
response = self.tsp_client.post_configuration(CONFIG_SOURCE_TYPE, params)
417434
assert response.status_code == 200
418435

419-
response = self.tsp_client.fetch_extensions()
420-
assert len(response.model.extension_set) == 1
436+
response = self.tsp_client.fetch_configurations(CONFIG_SOURCE_TYPE)
437+
assert len(response.model.configuration_set) > 0
438+
found = False
439+
for config in response.model.configuration_set:
440+
if config.id == self.name:
441+
found = True
442+
assert found
421443

422-
response = self.tsp_client.delete_extension(self.name)
444+
response = self.tsp_client.fetch_configuration(CONFIG_SOURCE_TYPE, self.name)
423445
assert response.status_code == 200
446+
assert response.model
447+
assert response.model.id == self.name
448+
449+
response = self.tsp_client.delete_configuration(CONFIG_SOURCE_TYPE, self.name)
450+
assert response.status_code == 200
451+
assert response.model
452+
assert response.model.id == self.name
453+
454+
def test_posted_configuration_deleted(self, extension):
455+
"""Expect no configuration after deletion."""
456+
params = {}
457+
params['path'] = extension
458+
self.tsp_client.post_configuration(CONFIG_SOURCE_TYPE, params)
459+
response = self.tsp_client.delete_configuration(CONFIG_SOURCE_TYPE, self.name)
460+
assert response.status_code == 200
461+
462+
response = self.tsp_client.fetch_configurations(CONFIG_SOURCE_TYPE)
463+
assert response.model.configuration_set
464+
465+
def test_put_configuration(self, extension):
466+
"""Expect successful update of configuartion."""
467+
params = {}
468+
params['path'] = extension
469+
self.tsp_client.post_configuration(CONFIG_SOURCE_TYPE, params)
424470

425-
def test_posted_extension_deleted(self, extension):
426-
"""Expect no extension after deletion."""
427-
self.tsp_client.post_extension(extension)
428-
response = self.tsp_client.delete_extension(self.name)
471+
response = self.tsp_client.put_configuration(CONFIG_SOURCE_TYPE, self.name, params)
429472
assert response.status_code == 200
473+
assert response.model
474+
assert response.model.id == self.name
430475

431-
response = self.tsp_client.fetch_extensions()
432-
assert not response.model.extension_set
476+
self.tsp_client.delete_configuration(CONFIG_SOURCE_TYPE, self.name)
433477

434478
@staticmethod
435479
def __requested_parameters(response):

tsp/configuration.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (C) 2020, 2023 - Ericsson
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
"""Configuration class file."""
24+
25+
NAME_KEY = "name"
26+
DESCTIPION_KEY = "description"
27+
ID_KEY = "id"
28+
SOURCE_TYPE_ID = "sourceTypeId"
29+
PARAMETER_KEY = "parameters"
30+
31+
# pylint: disable=too-few-public-methods
32+
class Configuration:
33+
'''
34+
Class to handle configurations available on the remote node
35+
'''
36+
def __init__(self, params):
37+
'''
38+
Constructor
39+
'''
40+
41+
if NAME_KEY in params:
42+
self.name = params.get(NAME_KEY)
43+
del params[NAME_KEY]
44+
else:
45+
self.name = ""
46+
47+
if DESCTIPION_KEY in params:
48+
self.description = params.get(DESCTIPION_KEY)
49+
del params[DESCTIPION_KEY]
50+
else:
51+
self.description = ""
52+
53+
if ID_KEY in params:
54+
# pylint: disable=invalid-name
55+
self.id = params.get(ID_KEY)
56+
del params[ID_KEY]
57+
else:
58+
self.id = "unknown-id"
59+
60+
if SOURCE_TYPE_ID in params:
61+
# pylint: disable=invalid-name
62+
self.source_type_id = params.get(SOURCE_TYPE_ID)
63+
del params[SOURCE_TYPE_ID]
64+
else:
65+
self.source_type_id = "unknown_source_type_id"
66+
67+
if PARAMETER_KEY in params:
68+
# pylint: disable=invalid-name
69+
self.parameters = params.get(PARAMETER_KEY)
70+
del params[PARAMETER_KEY]
71+
else:
72+
self.parameters = {}
73+
74+
75+
# pylint: disable=consider-using-f-string
76+
def to_string(self):
77+
'''
78+
to_string method
79+
'''
80+
return 'Configuration[name={0}, description={1}, id={2}, source_type_id={3}, parameters={4}]'.format(self.name,
81+
self.description, self.id, self.source_type_id, self.parameters)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (C) 2023 - Ericsson
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
"""Configuration parameter descriptors class file."""
24+
25+
KEY_NAME_KEY = "keyName"
26+
DESCTIPION_KEY = "description"
27+
DATA_TYPE_KEY = "dataType"
28+
REQUIRED_KEY = "isRequired"
29+
30+
# pylint: disable=too-few-public-methods
31+
class ConfigurationParameterDescriptor:
32+
'''
33+
Class to handle configuration parameter descriptor available on the remote node
34+
'''
35+
def __init__(self, params):
36+
'''
37+
Constructor
38+
'''
39+
40+
if KEY_NAME_KEY in params:
41+
self.key_name = params.get(KEY_NAME_KEY)
42+
del params[KEY_NAME_KEY]
43+
else:
44+
self.key_name = ""
45+
46+
if DESCTIPION_KEY in params:
47+
self.description = params.get(DESCTIPION_KEY)
48+
del params[DESCTIPION_KEY]
49+
else:
50+
self.description = ""
51+
52+
if DATA_TYPE_KEY in params:
53+
# pylint: disable=invalid-name
54+
self.data_type = params.get(DATA_TYPE_KEY)
55+
del params[DATA_TYPE_KEY]
56+
else:
57+
self.data_type = "STRING"
58+
59+
if REQUIRED_KEY in params:
60+
# pylint: disable=invalid-name
61+
self.is_required = params.get(REQUIRED_KEY)
62+
del params[REQUIRED_KEY]
63+
else:
64+
self.is_required = "unknown_source_type_id"
65+
66+
67+
# pylint: disable=consider-using-f-string
68+
def to_string(self):
69+
'''
70+
to_string method
71+
'''
72+
return 'ConfigurationParameterDescriptor[key_name={0}, description={1}, data_type={2}, is_required={3}]'.format(self.key_name,
73+
self.description, self.data_type, self.is_required)

0 commit comments

Comments
 (0)