Skip to content

Commit c10bb8a

Browse files
authored
Api (#3367)
* Remove simplistic "API" list from endpoints PBENCH-1119 With the REST-ification of the API, only a few of the APIs can still be called using the simplistic `{name: uri}` list, because URI parameters are needed and are no longer at the end of the URI: for example, `/api/v1/datasets/{dataset}/metadata`. The UI now has the `uriTemplate` method to help expand the `"uri"` template objects. Complete the transition by updating the remaining UI references and dropping the `api` object entirely.
1 parent 78dd636 commit c10bb8a

File tree

9 files changed

+32
-77
lines changed

9 files changed

+32
-77
lines changed

dashboard/src/actions/datasetListActions.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import * as TYPES from "./types";
22

33
import API from "../utils/axiosInstance";
4+
import { uriTemplate } from "utils/helper";
45

56
export const fetchPublicDatasets = () => async (dispatch, getState) => {
67
try {
78
dispatch({ type: TYPES.LOADING });
89
const endpoints = getState().apiEndpoint.endpoints;
910
const response = await API.get(
10-
`${endpoints?.api?.datasets_list}?metadata=dataset.uploaded&access=public`
11+
uriTemplate(endpoints, "datasets_list", {}),
12+
{ params: { metadata: "dataset.uploaded", access: "public" } }
1113
);
1214
if (response.status === 200 && response.data) {
1315
dispatch({

dashboard/src/actions/overviewActions.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as TYPES from "./types";
44
import { DANGER, ERROR_MSG } from "assets/constants/toastConstants";
55

66
import API from "../utils/axiosInstance";
7-
import { expandUriTemplate } from "../utils/helper";
7+
import { uriTemplate } from "../utils/helper";
88
import { findNoOfDays } from "utils/dateFunctions";
99
import { showToast } from "./toastActions";
1010
import { clearCachedSession } from "./authActions";
@@ -27,8 +27,8 @@ export const getDatasets = () => async (dispatch, getState) => {
2727
params.append("mine", "true");
2828

2929
const endpoints = getState().apiEndpoint.endpoints;
30-
const response = await API.get(endpoints?.api?.datasets_list, {
31-
params: params,
30+
const response = await API.get(uriTemplate(endpoints, "datasets_list"), {
31+
params,
3232
});
3333

3434
if (response.status === 200) {
@@ -127,7 +127,7 @@ export const updateDataset =
127127
const method = metaDataActions[actionType];
128128

129129
const endpoints = getState().apiEndpoint.endpoints;
130-
const uri = expandUriTemplate(endpoints, "datasets_metadata", {
130+
const uri = uriTemplate(endpoints, "datasets_metadata", {
131131
dataset: dataset.resource_id,
132132
});
133133
const response = await API.put(uri, {
@@ -176,7 +176,9 @@ export const deleteDataset = (dataset) => async (dispatch, getState) => {
176176
dispatch({ type: TYPES.LOADING });
177177
const endpoints = getState().apiEndpoint.endpoints;
178178
const response = await API.delete(
179-
`${endpoints.api.datasets}/${dataset.resource_id}`
179+
uriTemplate(endpoints, "datasets", {
180+
dataset: dataset.resource_id,
181+
})
180182
);
181183
if (response.status === 200) {
182184
const datasets = getState().overview.datasets;
@@ -257,7 +259,11 @@ export const publishDataset =
257259
const savedRuns = getState().overview.savedRuns;
258260

259261
const response = await API.post(
260-
`${endpoints.api.datasets}/${dataset.resource_id}?access=${updateValue}`
262+
uriTemplate(endpoints, "datasets", {
263+
dataset: dataset.resource_id,
264+
}),
265+
null,
266+
{ params: { access: updateValue } }
261267
);
262268
if (response.status === 200) {
263269
const dataIndex = savedRuns.findIndex(

dashboard/src/actions/tableOfContentActions.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import * as TYPES from "./types";
22
import API from "../utils/axiosInstance";
3-
import { expandUriTemplate } from "../utils/helper";
3+
import { uriTemplate } from "../utils/helper";
44

55
export const fetchTOC =
66
(param, parent, callForSubData) => async (dispatch, getState) => {
77
try {
88
const endpoints = getState().apiEndpoint.endpoints;
9-
const uri = expandUriTemplate(endpoints, "datasets_contents", {
9+
const uri = uriTemplate(endpoints, "datasets_contents", {
1010
dataset: param,
1111
target: parent,
1212
});

dashboard/src/utils/helper.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ export const uid = () => {
1010
*
1111
* @param {Object} endpoints - endpoint object from server
1212
* @param {string} name - name of the API to expand
13-
* @param {Object} args - value for each templated parameter
13+
* @param {Object} args - [Optional] value for each templated parameter
1414
* @return {string} - formatted URI
1515
*/
16-
export const expandUriTemplate = (endpoints, name, args) => {
16+
export const uriTemplate = (endpoints, name, args = {}) => {
1717
let uri = endpoints.uri[name].template;
1818
for (const [key, value] of Object.entries(args)) {
1919
uri = uri.replace(`{${key}}`, value);

lib/pbench/client/__init__.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,13 @@ def _uri(self, api: API, uri_params: Optional[JSONOBJECT] = None) -> str:
120120
Returns:
121121
A fully specified URI
122122
"""
123-
if not uri_params:
124-
return self.endpoints["api"][api.value]
125-
else:
126-
description = self.endpoints["uri"][api.value]
127-
template = description["template"]
128-
cnt = len(description["params"])
129-
if cnt != len(uri_params):
130-
raise IncorrectParameterCount(api, cnt, uri_params)
131-
return template.format(**uri_params)
123+
description = self.endpoints["uri"][api.value]
124+
template = description["template"]
125+
cnt = len(description["params"])
126+
params = uri_params if uri_params else {}
127+
if cnt != len(params):
128+
raise IncorrectParameterCount(api, cnt, params)
129+
return template.format(**params)
132130

133131
def get(
134132
self,

lib/pbench/server/api/resources/endpoint_configure.py

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -51,46 +51,22 @@ def get(self):
5151
including the Pbench dashboard UI. This includes:
5252
5353
openid-connect: A JSON object containing the OpenID Connect parameters
54-
required for the web client to use OIDC authentication.
54+
required for the web client to use OIDC authentication.
5555
identification: The Pbench server name and version
56-
api: A dict of the server APIs supported; we give a name, which
57-
identifies the service, and the full URI relative to the
58-
configured host name and port (local or remote reverse proxy).
59-
60-
This is dynamically generated by processing the Flask URI
61-
rules; refer to api/__init__.py for the code which creates
62-
those mappings, or test_endpoint_configure.py for code that
63-
validates the current set (and must be updated when the API
64-
set changes).
6556
uri: A dict of server API templates, where each template defines a
6657
template URI and a list of typed parameters.
6758
6859
We derive a "name" for each API by removing URI parameters and the API
6960
prefix (/api/v1/), then replacing the path "/" characters with
7061
underscores.
7162
72-
The "api" object contains a key for each API name, where the value is a
73-
simplified URI omitting URI parameters. The client must either know the
74-
required parameters and order, and connect them to the "api" value
75-
separated by slash characters, or refer to the "uri" templates.
76-
77-
E.g, "/api/v1/controllers/list" yields:
78-
79-
"controllers_list": "http://host/api/v1/controllers/list"
80-
81-
while "/api/v1/users/<string:username>" yields:
82-
83-
"users": "http://host/api/v1/users"
84-
85-
For URIs with multiple parameters, or embedded parameters, it may be
86-
easier to work with the template string in the "uri" object. The value
87-
of each API name key in the "uri" object is a minimal "schema" object
88-
defining the template string and parameters for the API. The "uri"
89-
value for the "users" API, for example, will be
63+
The "uri" object defines a template for each API name, defining a set of
64+
URI parameters that must be expanded in the template. For example, the
65+
API to get or modify metadata is:
9066
9167
{
92-
"template": "http://host/api/v1/users/{target_username}",
93-
"params": {"target_username": {"type": "string"}}
68+
"template": "http://host/api/v1/datasets/{dataset}/metadata",
69+
"params": {"dataset": {"type": "string"}}
9470
}
9571
9672
The template can be resolved in Python with:
@@ -137,7 +113,6 @@ def get(self):
137113
host_value,
138114
)
139115

140-
apis = {}
141116
templates = {}
142117

143118
# Iterate through the Flask endpoints to add a description for each.
@@ -156,7 +131,6 @@ def get(self):
156131
for match in matches
157132
},
158133
}
159-
url = self.param_template.sub("", url)
160134
path = rule.endpoint
161135

162136
# We have some URI endpoints that repeat a basic URI pattern.
@@ -168,12 +142,10 @@ def get(self):
168142
if path not in templates or (
169143
len(template["params"]) > len(templates[path]["params"])
170144
):
171-
apis[path] = urljoin(host, url)
172145
templates[path] = template
173146

174147
endpoints = {
175148
"identification": f"Pbench server {self.server_config.COMMIT_ID}",
176-
"api": apis,
177149
"uri": templates,
178150
}
179151

lib/pbench/test/functional/server/test_connect.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,15 @@ def test_connect(self, server_client: PbenchServerClient):
1212
assert server_client.session.headers["Accept"] == "application/json"
1313
endpoints = server_client.endpoints
1414
assert endpoints
15-
assert "api" in endpoints
1615
assert "identification" in endpoints
1716
assert "uri" in endpoints
1817

1918
# Verify that all expected endpoints are reported
20-
for a in endpoints["api"].keys():
21-
assert a in expected
2219
for a in endpoints["uri"].keys():
2320
assert a in expected
2421

2522
# Verify that no unexpected endpoints are reported
2623
for e in expected:
27-
assert e in endpoints["api"].keys()
2824
assert e in endpoints["uri"].keys()
2925

3026
# verify all the required openid-connect fields are present

lib/pbench/test/unit/client/test_connect.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ def test_connect(self):
3030
url,
3131
json={
3232
"identification": "string",
33-
"api": {},
3433
"uri": {},
3534
"openid": openid_dict,
3635
},
@@ -54,7 +53,6 @@ def test_connect(self):
5453
# Check that the fake endpoints we returned are captured
5554
endpoints = pbench.endpoints
5655
assert endpoints
57-
assert endpoints["api"] == {}
5856
assert endpoints["identification"] == "string"
5957
assert endpoints["uri"] == {}
6058
assert endpoints["openid"] == openid_dict

lib/pbench/test/unit/server/test_endpoint_configure.py

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,6 @@ def check_config(self, client, server_config, host, my_headers={}):
4141
uri = urljoin(host, uri_prefix)
4242
expected_results = {
4343
"identification": f"Pbench server {server_config.COMMIT_ID}",
44-
"api": {
45-
"datasets": f"{uri}/datasets",
46-
"datasets_contents": f"{uri}/datasets/contents",
47-
"datasets_daterange": f"{uri}/datasets/daterange",
48-
"datasets_detail": f"{uri}/datasets/detail",
49-
"datasets_inventory": f"{uri}/datasets/inventory",
50-
"datasets_list": f"{uri}/datasets",
51-
"datasets_mappings": f"{uri}/datasets/mappings",
52-
"datasets_metadata": f"{uri}/datasets/metadata",
53-
"datasets_namespace": f"{uri}/datasets/namespace",
54-
"datasets_search": f"{uri}/datasets/search",
55-
"datasets_values": f"{uri}/datasets/values",
56-
"endpoints": f"{uri}/endpoints",
57-
"server_audit": f"{uri}/server/audit",
58-
"server_settings": f"{uri}/server/settings",
59-
"upload": f"{uri}/upload",
60-
},
6144
"uri": {
6245
"datasets": {
6346
"template": f"{uri}/datasets/{{dataset}}",

0 commit comments

Comments
 (0)