Skip to content

Commit 1dbad11

Browse files
authored
Some API documentation fixes (#3441)
* Some API documentation fixes PBENCH-819 This is primarily a minor "cleanup pass" to make some specific example paths more generic and retire a long-standing story. Along the way I also found a few places I'd missed during the REST API changes so I fixed them as well. Finally, I added a `relay.md` API file for the new Relay API. Any other bugs, omissions, or other comments in API documentation could also be considered "in scope" here.
1 parent f5a6b12 commit 1dbad11

File tree

6 files changed

+204
-40
lines changed

6 files changed

+204
-40
lines changed

docs/Server/API/README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ The Pbench Server provides a set of HTTP endpoints to manage user
77
authentication and curated performance information, called "dataset resources"
88
or just "datasets".
99

10-
The [V1 API](V1/README.md) provides a functional interface that's not quite
11-
standard REST. The intent is to migrate to a cleaner resource-oriented REST
12-
style for a future V2 API.
10+
The [V1 API](V1/README.md) provides a REST-like functional interface.
1311

14-
The Pbench Server primarily uses serialized JSON parameters (mimetype
15-
`application/json`) both for request bodies and response bodies. A few
16-
exceptions use raw byte streams (`application/octet-stream`) to allow uploading
17-
new datasets and to access individual files from a dataset.
12+
The Pbench Server APIs accept parameters from a variety of sources. See the
13+
individual API documentation for details.
14+
1. Some parameters, especially "resource ids", are embedded in the URI, such as
15+
`/api/v1/datasets/<resource_id>`;
16+
2. Some parameters are passed as query parameters, such as
17+
`/api/v1/datasets?name:fio`;
18+
3. For `PUT` and `POST` APIs, parameters may also be passed as a JSON
19+
(`application/json` content type) request payload, such as
20+
`{"metadata": {"dataset.name": "new name"}}`

docs/Server/API/V1/README.md

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -132,20 +132,3 @@ through the `directories` list of each
132132
The [inventory](inventory.md) API returns the raw byte stream of any regular
133133
file within the directory hierarchy, including log files, postprocessed JSON
134134
files, and benchmark result text files.
135-
136-
### Example
137-
138-
```
139-
def directory(request, url: str, name: str = "/", level: int = 0):
140-
ls = request.get(url).get_json()
141-
print(f"{' '*level}{name}")
142-
for d in ls.directories:
143-
directory(request, level + 1, d.name, d.url)
144-
for f in ls.files:
145-
print(f"{' '*(level+1)}{f.name})
146-
bytes = request.get(f.url)
147-
# display byte stream:
148-
# inline on terminal doesn't really make sense
149-
150-
directory(request, "http://host.example.com/api/v1/contents/<dataset>/")
151-
```

docs/Server/API/V1/contents.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,33 +75,33 @@ Pbench returns a JSON object with two list fields:
7575
{
7676
"directories": [
7777
{
78-
"name": "1-iter1",
78+
"name": "dir1",
7979
"type": "dir",
80-
"uri": "http://hostname/api/v1/datasets/contents/<id>/1-iter1"
80+
"uri": "http://hostname/api/v1/datasets/<id>/contents/dir1"
8181
},
8282
{
83-
"sysinfo",
83+
"name": "dir2",
8484
"type": "dir",
85-
"uri": "http://hostname/api/v1/datasets/contents/<id>/sysinfo"
85+
"uri": "http://hostname/api/v1/datasets/<id>/contents/dir2"
8686
},
8787
...
8888
],
8989
"files": [
9090
{
91-
"name": ".iterations",
91+
"name": "file.txt",
9292
"mtime": "2022-05-18T16:02:30",
9393
"size": 24,
9494
"mode": "0o644",
9595
"type": "reg",
96-
"uri": "http://hostname/api/v1/datasets/inventory/<id>/.iterations"
96+
"uri": "http://hostname/api/v1/datasets/<id>/inventory/file.txt"
9797
},
9898
{
99-
"name": "iteration.lis",
99+
"name": "data.lis",
100100
"mtime": "2022-05-18T16:02:06",
101101
"size": 18,
102102
"mode": "0o644",
103103
"type": "reg",
104-
"uri": "http://hostname/api/v1/datasets/inventory/<id>/iteration.lis"
104+
"uri": "http://hostname/api/v1/datasets/<id>/inventory/data.lis"
105105
},
106106
...
107107
]
@@ -126,7 +126,12 @@ The `type` codes are:
126126
{
127127
"name": "reference-result",
128128
"type": "sym",
129-
"uri": "http://hostname/api/v1/datasets/contents/<id>/sample1"
129+
"uri": "http://hostname/api/v1/datasets/<id>/contents/linkresult"
130+
},
131+
{
132+
"name": "directory",
133+
"type": "dir",
134+
"uri": "http://hostname/api/v1/datasets/<id>/contents/directory"
130135
}
131136
```
132137

@@ -154,6 +159,6 @@ URI returning the linked file's byte stream.
154159
"size": 18,
155160
"mode": "0o644",
156161
"type": "reg",
157-
"uri": "http://hostname/api/v1/datasets/inventory/<id>/<path>"
162+
"uri": "http://hostname/api/v1/datasets/<id>/inventory/<path>"
158163
}
159164
```

docs/Server/API/V1/inventory.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ The resource ID of a Pbench dataset on the server.
1111

1212
`<path>` string \
1313
The resource path of an item in the dataset inventory, as captured by the
14-
Pbench Agent packaging; for example, `/metadata.log` for the dataset metadata,
15-
or `/1-default/sample1/result.txt` for the default first iteration results.
14+
Pbench Agent packaging; for example, `/metadata.log` for a file named
15+
`metadata.log` at the top level of the dataset tarball, or `/dir1/dir2/file.txt`
16+
for a `file.txt` file in a directory named `dir2` within a directory called
17+
`dir1` at the top level of the dataset tarball.
1618

1719
## Request headers
1820

@@ -25,6 +27,23 @@ E.g., `authorization: bearer <token>`
2527
`content-type: application/octet-stream` \
2628
The return is a raw byte stream representing the contents of the named file.
2729

30+
`content-disposition: <action>; filename=<name>` \
31+
This header defines the recommended client action on receiving the byte stream.
32+
The `<action>` types are either `inline` which suggests that the data can be
33+
displayed "inline" by a web browser or `attachment` which suggests that the data
34+
should be saved into a new file. The `<name>` is the original filename on the
35+
Pbench Server. For example,
36+
37+
```
38+
content-disposition: attachment; filename=pbench-fio-config-2023-06-29-00:14:50.tar.xz
39+
```
40+
41+
or
42+
43+
```
44+
content-disposition: inline; filename=data.txt
45+
```
46+
2847
## Resource access
2948

3049
* Requires `READ` access to the `<dataset>` resource
@@ -48,7 +67,7 @@ exist.
4867

4968
`415` **UNSUPPORTED MEDIA TYPE** \
5069
The `<path>` refers to a directory. Use
51-
`/api/v1/dataset/contents/<dataset><path>` to request a JSON response document
70+
`/api/v1/dataset/<dataset>/contents/<path>` to request a JSON response document
5271
describing the directory contents.
5372

5473
`503` **SERVICE UNAVAILABLE** \

docs/Server/API/V1/relay.md

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# `POST /api/v1/relay/<uri>`
2+
3+
This API creates a dataset resource by reading data from a Relay server. There
4+
are two distinct steps involved:
5+
6+
1. A `GET` on the provided URI must return a "Relay manifest file". This is a
7+
JSON file (`application/json` MIME format) providing the original tarball
8+
filename, the tarball's MD5 hash value, a URI to read the tarball file, and
9+
optionally metadata key/value pairs to be applied to the new dataset. (See
10+
[Manifest file keys](#manifest-file-keys).)
11+
2. A `GET` on the Relay manifest file's `uri` field value must return the
12+
tarball file as an `application/octet-stream` payload, which will be stored by
13+
the Pbench Server as a dataset.
14+
15+
## URI parameters
16+
17+
`<uri>` string \
18+
The Relay server URI of the tarball's manifest `application/json` file. This
19+
JSON object must provide a set of parameter keys as defined below in
20+
[Manifest file keys](#manifest-file-keys).
21+
22+
## Manifest file keys
23+
24+
For example,
25+
26+
```json
27+
{
28+
"uri": "https://relay.example.com/52adfdd3dbf2a87ed6c1c41a1ce278290064b0455f585149b3dadbe5a0b62f44",
29+
"md5": "22a4bc5748b920c6ce271eb68f08d91c",
30+
"name": "fio_rw_2018.02.01T22.40.57.tar.xz",
31+
"access": "private",
32+
"metadata": ["server.origin:myrelay", "global.agent:cloud1"]
33+
}
34+
```
35+
36+
`access`: [ `private` | `public` ] \
37+
The desired initial access scope of the dataset. Select `public` to make the
38+
dataset accessible to all clients, or `private` to make the dataset accessible
39+
only to the owner. The default access scope if the key is omitted from the
40+
manifest is `private`.
41+
42+
For example, `"access": "public"`
43+
44+
`md5`: tarball MD5 hash \
45+
The MD5 hash of the compressed tarball file. This must match the actual tarball
46+
octet stream specified by the manifest `uri` key.
47+
48+
`metadata`: [metadata key/value strings] \
49+
A set of desired Pbench Server metadata key values to be assigned to the new
50+
dataset. You can set the initial resource name (`dataset.name`), for example, as
51+
well as assigning any keys in the `global` and `user` namespaces. See
52+
[metadata](../metadata.md) for more information.
53+
54+
In particular the client can set any of:
55+
* `dataset.name`: [default dataset name](../metadata.md#datasetname)
56+
* `server.origin`: [dataset origin](../metadata.md#serverorigin)
57+
* `server.archiveonly`: [suppress indexing](../metadata.md#serverarchiveonly)
58+
* `server.deletion`: [default dataset expiration time](../metadata.md#serverdeletion).
59+
60+
`name`: The original tarball file name \
61+
The string value must represent a legal filename with the compound type of
62+
`.tar.xz` representing a `tar` archive compressed with the `xz` program.
63+
64+
`uri`: Relay URI resolving to the tarball file \
65+
An HTTP `GET` on this URI, exactly as recorded, must return the original tarball
66+
file as an `application/octet-stream`.
67+
68+
## Request headers
69+
70+
`authorization: bearer` token \
71+
*Bearer* schema authorization assigns the ownership of the new dataset to the
72+
authenticated user. E.g., `authorization: bearer <token>`
73+
74+
`content-length` tarball size \
75+
The size of the request octet stream in bytes. Generally supplied automatically by
76+
an upload agent such as Python `requests` or `curl`.
77+
78+
## Response headers
79+
80+
`content-type: application/json` \
81+
The return is a serialized JSON object with status information.
82+
83+
## Response status
84+
85+
`200` **OK** \
86+
Successful request. The dataset MD5 hash is identical to that of a dataset
87+
previously uploaded to the Pbench Server. This is assumed to be an identical
88+
tarball, and the secondary URI (the `uri` field in the Relay manifest file)
89+
has not been accessed.
90+
91+
`201` **CREATED** \
92+
The tarball was successfully uploaded and the dataset has been created.
93+
94+
`400` **BAD_REQUEST** \
95+
One of the required headers is missing or incorrect, invalid query parameters
96+
were specified, or a bad value was specified for a query parameter. The return
97+
payload will be a JSON document with a `message` field containing details.
98+
99+
`401` **UNAUTHORIZED** \
100+
The client is not authenticated.
101+
102+
`502` **BAD GATEWAY** \
103+
This means that a problem occurred reading either the manifest file or the
104+
tarball from the Relay server. The return payload will be a JSON document with
105+
a `message` field containing more information.
106+
107+
`503` **SERVICE UNAVAILABLE** \
108+
The server has been disabled using the `server-state` server configuration
109+
setting in the [server configuration](./server_config.md) API. The response
110+
body is an `application/json` document describing the current server state,
111+
a message, and optional JSON data provided by the system administrator.
112+
113+
## Response body
114+
115+
The `application/json` response body consists of a JSON object containing a
116+
`message` field. On failure this will describe the nature of the problem and
117+
in some cases an `errors` array will provide details for cases where multiple
118+
problems can occur.
119+
120+
```json
121+
{
122+
"message": "File successfully uploaded"
123+
}
124+
```
125+
126+
or
127+
128+
```json
129+
{
130+
"message": "Dataset already exists",
131+
}
132+
```
133+
134+
or
135+
136+
```json
137+
{
138+
"message": "at least one specified metadata key is invalid",
139+
"errors": [
140+
"Metadata key 'server.archiveonly' value 'abc' for dataset must be a boolean",
141+
"improper metadata syntax dataset.name=test must be 'k:v'",
142+
"Key test.foo is invalid or isn't settable",
143+
],
144+
}
145+
```

docs/Server/API/V1/upload.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,22 @@ a message, and optional JSON data provided by the system administrator.
8282

8383
## Response body
8484

85-
The `application/json` response body consists of a JSON object giving a detailed
86-
message on success or failure:
85+
The `application/json` response body consists of a JSON object containing a
86+
`message` field. On failure this will describe the nature of the problem and
87+
in some cases an `errors` array will provide details for cases where multiple
88+
problems can occur.
89+
90+
```json
91+
{
92+
"message": "File successfully uploaded"
93+
}
94+
```
95+
96+
or
8797

8898
```json
8999
{
90100
"message": "Dataset already exists",
91-
"errors": [ ]
92101
}
93102
```
94103

0 commit comments

Comments
 (0)