215 lines
6.7 KiB
Markdown
215 lines
6.7 KiB
Markdown
|
# Introduction
|
||
|
|
||
|
The `sym_upload` tool is able to operate in `sym-upload-v2` protocol mode, in
|
||
|
addition to the legacy protocol (which will be referred to as `sym-upload-v1`
|
||
|
for the rest of this document). For now `sym-upload-v2` is HTTP/REST-based but
|
||
|
it could be extended to operate over gRPC instead, in the future.
|
||
|
|
||
|
# Table of Contents
|
||
|
* [Why](#why)
|
||
|
* [How](#how)
|
||
|
* [Uploading](#uploading)
|
||
|
* [Uploading with `sym_upload`](#uploading-with-sym_upload)
|
||
|
* [Uploading with curl](#uploading-with-curl)
|
||
|
* [Serving the `sym-upload-v2` protocol](#serving-the-sym-upload-v2-protocol)
|
||
|
* [Authenticate using `key`](#authenticate-using-key)
|
||
|
* [Symbol `checkStatus`](#symbol-checkstatus)
|
||
|
* [Upload `create`](#upload-create)
|
||
|
* [Uploading the symbol file](#uploading-the-symbol-file)
|
||
|
* [Upload complete](#upload-complete)
|
||
|
|
||
|
|
||
|
# Why
|
||
|
|
||
|
Using `sym_upload` in `sym-upload-v2` protocol mode has the following features
|
||
|
beyond `sym-upload-v1`:
|
||
|
* Authentication via `key` (arbitrary secret).
|
||
|
* Symbol identifier (product of `debug_file` and `debug_id`, as recorded in
|
||
|
output from `dump_syms`) can be checked against existing symbol information on
|
||
|
server. If it's present, then the upload is skipped entirely.
|
||
|
|
||
|
# How
|
||
|
|
||
|
## Uploading
|
||
|
|
||
|
### Uploading with `sym_upload`
|
||
|
|
||
|
Uploading in `sym-upload-v2` protocol mode is easy. Invoke `sym_upload` like
|
||
|
```
|
||
|
$ ./sym_upload -p sym-upload-v2 [-k <API-key>] <symbol-file> <API-URL>
|
||
|
```
|
||
|
|
||
|
Where `symbol-file` is a symbol file created by `dump_syms`, `API-URL` is the
|
||
|
URL of your `sym-upload-v2` API service (see next section for details), and
|
||
|
`API-key` is a secret known to your uploader and server.
|
||
|
|
||
|
For more options see `sym_upload --help`.
|
||
|
|
||
|
### Uploading with curl
|
||
|
|
||
|
As an example, if:
|
||
|
* Your API's URL was "https://sym-upload-api".
|
||
|
* Your service has assigned you `key` "myfancysecret123".
|
||
|
* You wanted to upload the symbol file at "path/to/file_name", with
|
||
|
`debug_file` being "file_name" and `debug_id` being
|
||
|
"123123123123123123123123123". Normally you would read these values from
|
||
|
"path/to/file_name", which in turn was generated by `dump_syms`.
|
||
|
|
||
|
Then you might run:
|
||
|
```
|
||
|
$ curl https://sym-upload-api/symbols/file_name/123123123123123123123123123:checkStatus?key=myfancysecret123
|
||
|
```
|
||
|
|
||
|
And, upon seeing that this `debug_file`/`debug_id` combo is missing from symbol
|
||
|
storage then you could run:
|
||
|
```
|
||
|
$ curl --request POST https://sym-upload-api/uploads:create?key=myfancysecret123
|
||
|
```
|
||
|
|
||
|
Which returns `upload_url` "https://upload-server/42?creds=shhhhh" and
|
||
|
`upload_key` "42". Next you upload the file directly like:
|
||
|
```
|
||
|
$ curl -T path/to/file_name "https://upload-server/42?creds=shhhhh"
|
||
|
```
|
||
|
|
||
|
Once the HTTP PUT is complete, run:
|
||
|
```
|
||
|
$ curl --header "Content-Type: application/json" \
|
||
|
--request POST \
|
||
|
--data '{symbol_id:{"debugFile":"file_name",'\
|
||
|
'"debugId":"123123123123123123123123123"}}' \
|
||
|
https://sym-upload-api/uploads/42:complete?key=myfancysecret123
|
||
|
```
|
||
|
|
||
|
### Serving the `sym-upload-v2` Protocol
|
||
|
|
||
|
The protocol is currently defined only in HTTP/REST. There are three necessary
|
||
|
REST operations to implement in your service:
|
||
|
* `/symbols/<debug_file>/<debug_id>:checkStatus?key=<key>`
|
||
|
* `/uploads:create?key=<key>`
|
||
|
* `/uploads/<upload_key>:complete?key=<key>`
|
||
|
|
||
|
#### Authenticate Using `key`
|
||
|
|
||
|
The query string arg `key` contains some secret that both the uploader and
|
||
|
server understand. It is up to the service implementer to decide on what
|
||
|
constitutes a valid `key`, how the uploader acquires one, and how to handle
|
||
|
requests made with invalid ones.
|
||
|
|
||
|
#### Symbol `checkStatus`
|
||
|
|
||
|
```
|
||
|
/symbols/<debug_file>/<debug_id>:checkStatus?key=<key>
|
||
|
```
|
||
|
|
||
|
This operation expects an empty (or no) JSON payload in the request.
|
||
|
|
||
|
This operation should return the status of the symbol file uniquely identified
|
||
|
by the given `debug_file` and `debug_id`. JSON schema:
|
||
|
```
|
||
|
{
|
||
|
"type": object",
|
||
|
"properties": {
|
||
|
"status": {
|
||
|
"type": "string",
|
||
|
"enum": ["STATUS_UNSPECIFIED", "MISING", "FOUND"],
|
||
|
"required": true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Where `MISSING` denotes that the symbol file does not exist on the server and
|
||
|
`FOUND` denotes that the symbol file exists on the server.
|
||
|
|
||
|
#### Upload `create`
|
||
|
|
||
|
```
|
||
|
/uploads:create?key=<key>
|
||
|
```
|
||
|
|
||
|
This operation expects an empty (or no) JSON payload in the request.
|
||
|
|
||
|
This operation should return a URL that uploader can HTTP PUT their symbol file
|
||
|
to, along with an "upload key" that can be used to notify the service once the
|
||
|
file upload is completed. JSON schema:
|
||
|
```
|
||
|
{
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"upload_url": {
|
||
|
"type: "string",
|
||
|
"required": true
|
||
|
},
|
||
|
"upload_key": {
|
||
|
"type": "string",
|
||
|
"required": true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Since this REST API operation can be authenticated via the `key` query string
|
||
|
arg, the service can return a URL that encodes permission delegation to the
|
||
|
upload endpoint resource and thereby constrain the ability to upload to those
|
||
|
with valid `key`s.
|
||
|
|
||
|
#### Uploading the Symbol File
|
||
|
|
||
|
Note that the actual symbol upload step is _not_ part of the REST API. The
|
||
|
upload URL obtained in the above operation is meant to be used as the endpoint
|
||
|
for a normal HTTP PUT request for the contents of the symbol file. Once that
|
||
|
HTTP PUT request is completed use the upload `complete` operation.
|
||
|
|
||
|
#### Upload `complete`
|
||
|
|
||
|
```
|
||
|
/uploads/<upload_key>:complete?key=<key>
|
||
|
```
|
||
|
|
||
|
This operation expects a JSON payload in the HTTP request body with the
|
||
|
following schema:
|
||
|
```
|
||
|
{
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"symbol_id": {
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"debug_file": {
|
||
|
"type": "string",
|
||
|
"required": true
|
||
|
},
|
||
|
"debug_id": {
|
||
|
"type": "string",
|
||
|
"required": true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
This operation should cause the symbol storage back-end (however implemented)
|
||
|
to consume the symbol file identified by `upload_key`. It is up to the service
|
||
|
implementation to decide how uploads are assigned `upload_key`s and how to
|
||
|
retrieve a completed upload by its `upload_key`. If the symbol file cannot be
|
||
|
found, is malformed, or the operation cannot be completed for any other reason
|
||
|
then an HTTP error will be returned. JSON schema of non-error responses:
|
||
|
```
|
||
|
{
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"result": {
|
||
|
"type": string,
|
||
|
"enum": ["RESULT_UNSPECIFIED", "OK", "DUPLICATE_DATA"],
|
||
|
"required": true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Where `OK` denotes that the symbol storage was updated with the new symbol file
|
||
|
and `DUPLICATE_DATA` denotes that the symbol file data was identical to data
|
||
|
already in symbol storage and therefore nothing changed.
|