Skip to content

Commit

Permalink
Merge pull request #8 from bbc/sammg-use-stoplight-elements
Browse files Browse the repository at this point in the history
Switch to Stoplight Elements for docs render
  • Loading branch information
samdbmg authored Dec 20, 2023
2 parents b24263c + 68f7980 commit b557c46
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 35 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Users of TAMS are insulated from the details of the underlying storage.

## Documentation
- OpenAPI Specification: [TimeAddressableMediaStore.yaml](./api/TimeAddressableMediaStore.yaml)
- Rendered Documentation: [TimeAddressableMediaStore.html](https://bbc.github.io/tams/TimeAddressableMediaStore.html)
- Rendered Documentation: [https://bbc.github.io/tams](https://bbc.github.io/tams)

This repo contains some automation to run a mock version of the API using [Stoplight Prism](https://stoplight.io/open-source/prism). To run the mock server using Docker, try something like the command below (or run `make mock-server-up`):
```
Expand All @@ -48,17 +48,17 @@ The Flow model is aligned with the principles and schemas of [AMWA NMOS IS-04](h
### Reading and Writing in the Store
The process of reading from the store is:
1. Client identifies the Flow ID and timerange of interest
2. Client makes a request to [`GET flows/<flow_id>/segments?timerange=<timerange>`](https://bbc.github.io/tams/TimeAddressableMediaStore.html#operation/GET_flows-flowId-segments) and receives a list of segments, timeranges and download URLs
2. Client makes a request to [`GET flows/<flow_id>/segments?timerange=<timerange>`](https://bbc.github.io/tams/#/operations/GET_flows-flowId-segments) and receives a list of segments, timeranges and download URLs
3. Client downloads each URL, concatenates the segments together and unwraps the grains within
4. The first and last Flow Segment may contain more grains than requested, so the client should skip any received not in the requested timerange

The process of writing to the store is:
1. Client creates a Flow if necessary by making a request to [`PUT flows/<flow_id>`](https://bbc.github.io/tams/TimeAddressableMediaStore.html#operation/PUT_flows-flowId)
2. Client makes a request to [`POST flows/<flow_id>/storage`](https://bbc.github.io/tams/TimeAddressableMediaStore.html#operation/POST_flows-flowId-storage) with the timerange to be written
1. Client creates a Flow if necessary by making a request to [`PUT flows/<flow_id>`](https://bbc.github.io/tams/#/operations/PUT_flows-flowId)
2. Client makes a request to [`POST flows/<flow_id>/storage`](https://bbc.github.io/tams/#/operations/POST_flows-flowId-storage) with the timerange to be written
3. Store responds with a list of segment timeranges and URLs to PUT segments to, along with an optional `pre` URL to call before writing
4. If a `pre` URL was given, client calls it
5. Client breaks content into segments as instructed and uploads it
6. Client makes requests to [`POST flows/<flow_id>/segments`](https://bbc.github.io/tams/TimeAddressableMediaStore.html#operation/POST_flows-flowId-segments) with details of each new segment created, to register them on the timeline
6. Client makes requests to [`POST flows/<flow_id>/segments`](https://bbc.github.io/tams/#/operations/POST_flows-flowId-segments) with details of each new segment created, to register them on the timeline

### Flows, Sources and Mutation
Flows in the store are assumed to be immutable: once a grain has been written to a point on the timeline on a specific Flow, it cannot be changed. However Flows can always be extended, with empty spaces on the timeline filled in, and areas of the timeline can be permanently erased.
Expand Down
2 changes: 1 addition & 1 deletion api/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
docs/TimeAddressableMediaStore.html
docs/TimeAddressableMediaStore_bundled.yaml
4 changes: 4 additions & 0 deletions api/.spectral.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
extends: spectral:oas
rules:
# Reduce severity of unused components: they're needed for docs readability
oas3-unused-component: info
16 changes: 10 additions & 6 deletions api/Dockerfile.multi
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,25 @@ COPY ./schemas ./schemas
COPY ./TimeAddressableMediaStore.yaml .

###############################################################################
# Stage: oasvalidate - Validates OpenAPI specifications
# Stage: bundle - Bundles specification and schemas into a single file
###############################################################################
FROM redocly/openapi-cli AS oasvalidate
WORKDIR /data/
FROM redocly/cli as bundle

COPY ./bundle-api.sh /bundle-api.sh

# Copy in documentation source files
COPY --from=layer /api /data

COPY .redocly.lint-ignore.yaml /data/
ENTRYPOINT [ "/bundle-api.sh" ]

###############################################################################
# Stage: oasrender - Renders OpenAPI specifications
# Stage: oaslint - Validates OpenAPI specifications
###############################################################################
FROM ghcr.io/redocly/redoc/cli:v2.0.0-rc.59 AS oasrender
FROM stoplight/spectral:6.10 as oaslint

WORKDIR /data/

COPY .spectral.yaml /data/

# Copy in documentation source files
COPY --from=layer /api /data
21 changes: 12 additions & 9 deletions api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ topdir:=$(realpath $(dir $(word $(NUM_OF_PARENT),$(MAKEFILE_LIST))))

all: help


build-lint:
docker pull ap-docker.artifactory.labs.bbc/cloudfit/cloudfit_base:latest >/dev/null 2>/dev/null || true
DOCKER_BUILDKIT=1 docker build -f Dockerfile.multi --build-arg VERSION=0.0.1 --build-arg BUILD_TAG=local --target oasvalidate -t tams_api_oasvalidate:local .
docker pull stoplight/spectral:6.10 >/dev/null 2>/dev/null || true
DOCKER_BUILDKIT=1 docker build -f Dockerfile.multi --target oaslint -t tams_api_oaslint:local .

lint: build-lint
docker run --rm tams_api_oasvalidate:local lint /data/TimeAddressableMediaStore.yaml
docker run --rm tams_api_oaslint:local lint --fail-severity=warn /data/TimeAddressableMediaStore.yaml


build-bundle:
docker pull redocly/cli:latest >/dev/null 2>/dev/null || true
DOCKER_BUILDKIT=1 docker build -f Dockerfile.multi --target bundle -t tams_api_bundle:local .

build-render:
docker pull ap-docker.artifactory.labs.bbc/cloudfit/cloudfit_base:latest >/dev/null 2>/dev/null || true
DOCKER_BUILDKIT=1 docker build -f Dockerfile.multi --build-arg VERSION=0.0.1 --build-arg BUILD_TAG=local --target oasrender -t tams_api_oasrender:local .
docs/TimeAddressableMediaStore_bundled.yaml: build-bundle
docker run --rm tams_api_bundle:local bundle /data/TimeAddressableMediaStore.yaml > $@

render: build-render
docker run --rm -v "${topdir}/docs:/docs" tams_api_oasrender:local bundle /data/TimeAddressableMediaStore.yaml -o /docs/TimeAddressableMediaStore.html
render: docs/TimeAddressableMediaStore_bundled.yaml


mock-server-up:
Expand All @@ -40,4 +43,4 @@ help:
@echo "make mock-server-down - Stop the mock API server"
@echo "make mock-server-healthy - Connect to mock API server, confirm it is working"

.PHONY: all build-lint lint build-render render mock-server-up mock-server-down mock-server-healthy help
.PHONY: all build-lint lint build-bundle render mock-server-up mock-server-down mock-server-healthy help
19 changes: 10 additions & 9 deletions api/TimeAddressableMediaStore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,14 @@ info:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
servers:
- url: 'http://localhost:4010'
description: Local mock of API
- url: 'https://example.com/tams/{version}'
description: Example TAMS service
variables:
version:
description: API version
default: version
- url: /tams/{version}
description: Local mock of API and service running locally
variables:
version:
description: API version
default: version
default: v0.1
security:
- {}
- basic_auth: []
Expand Down Expand Up @@ -734,7 +730,7 @@ paths:
get:
description: |
List deletion requests currently being worked on, for monitoring in development.
This will not necessarily list all requests, nor return a consistent set in any particular order,
and should not be relied upon by clients. However if there are any requests in the system, it will
always return at least one.
Expand Down Expand Up @@ -772,7 +768,7 @@ paths:
get:
description: |
Get information about a range of FlowSegments that are being deleted.
A deletion request is created when a client DELETEs a long ranges of segments, which takes longer than
a single HTTP request. Clients will be redirected here to monitor the request's progress.
operationId: GET_flow-delete-requests-request-id
Expand All @@ -790,9 +786,11 @@ paths:
components:
schemas:
uuid:
title: UUID
pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
type: string
timestamp_type:
title: Timestamp
description: |
A signed nanosecond resolution timestamp represented as <sign><seconds>:<nanoseconds>. The intended
interpretation of the value is assumed to be defined elsewhere.
Expand All @@ -806,6 +804,7 @@ components:
type: string
pattern: '^-?\d+:\d+$'
timerange_type:
title: TimeRange
description: |
A time range of timestamps. It is represented using a pair ot timestamps with inclusivity and exclusivity markers.
Expand All @@ -820,13 +819,15 @@ components:
type: string
pattern: '^(\[|\()?(-?\d+:\d+)?(_(-?\d+:\d+)?)?(\]|\))?$'
flowformat:
title: Flow Format
description: identifies the flow format using a URN string.
enum:
- urn:x-nmos:format:video
- urn:x-nmos:format:audio
- urn:x-nmos:format:data
type: string
mimetype:
title: MIME Type
pattern: .*/.*
description: MIME Type string.
type: string
Expand Down
7 changes: 7 additions & 0 deletions api/bundle-api.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh
set -euo pipefail

# Custom script to run the Redocly CLI bundler, then work around https://github.com/Redocly/redocly-cli/issues/792
# Passes all CLI args to the Redocly CLI, then calls `sed` to make manual edits as needed
redocly $@ | \
sed -e s_http-request.json_\'#/components/schemas/http-request\'_g
13 changes: 9 additions & 4 deletions api/docs/index.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
<!DOCTYPE html>
<html>
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Refresh" content="0; url='TimeAddressableMediaStore.html'" />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Time Addressable Media API</title>

<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
</head>
<body>
<p>Redirecting...</p>
<elements-api id="docs" router="hash" layout="sidebar" tryItEnabled="false" apiDescriptionUrl="./TimeAddressableMediaStore_bundled.yaml"></elements-api>
</body>
</html>
2 changes: 1 addition & 1 deletion api/schemas/flow-storage.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"type": "object",
"title": "Media Bucket Segment Store",
"description": "Gives information on storage for particular flow segments. This example is for a media store that provided URLs for storing media objects in bucket. Different backends may add additional/different fields",
"title": "storage",
"properties": {
"pre": {
"type": "array",
Expand Down
1 change: 1 addition & 0 deletions api/schemas/http-request.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"type": "object",
"title": "HTTP Request",
"description": "Gives information on a particular http request a client should perform",
"required": [
"url"
Expand Down

0 comments on commit b557c46

Please sign in to comment.