Media Magic
Mono repo for the Media Magic Core project.
Project structure
infrastructure/new - contains the new Pulumi infrastructure code. Any service specific infrastructure will be moved from this directory into the appropriate service directory over. The wider platyform infra will be moved from the infrastructure/old (Terraform), into Pulumi as well.
libs - internal shared libraries. For example, Abzu, which is our internal framework for creating Go based webservices within Media Magic. This contains common tooling such as creating network requests, DI containers, cache and database connections, config management and more.
services - contains all of the webservices that make up Media Magic. Most of the metadata is managed by Hasura, however there is quite a lot of additional business logic, handled by custom web services. Some of these respond to Hasura events, some are standalone GraphQL services, which Hasura federates into its own schema.
scripts - contains end to end scripts
webapps - contains any user interfaces, such as the test UI, which was created to test the API and assist UI teams, serving as an example as to how to communicate, authenticate and use Media Magic. It also contains a quick way of generating user and organisation tokens.
deploy.sh - is a script that listens for changes within the microservices directory, and deploys any that have changed. (currently not in use)
docker-compose.yml - for running the entire platform locally (needs updating currently).
bins - is where compile binaries for each service are stored, these are not kept in the Gitlab repository, and are in the gitignore. To generate these, run
$ make build-all-binaries
.test-assets - is where test files such as images and videos are kept, as well as JSON payloads for testing against the REST api itself.
Known issues / to be improved
More tests / integration tests where possible.
User Journey
A user will sign-up via Auth0, and the Auth0 UI library. The user service exposes the endpoints needed for Auth0 to complete the authentication process.
A user token will be issued, this token is attached to a single user. This token is an OIDC compliant JWT token.
A user token has access to create deployments, upload media and list jobs/deployments/models, essentially the core functionality.
A user can then create an organisation, which can encapsulate multiple users around the same resources. This will require invites, which we will be adding at a later date.
Once a user has created an organisation, they can create an organisation token. Resources created/fetched using an organisation token will be stored against that organisation id, rather than the individual user. If you use a user token, you will not be able to use these resources.
A user, or an organisation can upload media. Each media asset has an individual ID.
A user, or an organisation can then create a deployment, which will need media ID's and a model ID, which can be found using the list models endpoint. Models are references to models deployed into our cluster manager and on premise hardware.
A deployment will create a job, which represents the state of a deployment against the cluster manager.
A user, or an organisation can then list jobs to see the output and any generated urls for any results created.
Running Locally
Per Service
Each service has a Makefile, and each service has a $ make run
command which runs the service locally.
You will need to use something like grpcurl to test gRPC endpoints locally. Each service also has a $ make start.local.dependencies
, which runs a Postgres and Redis docker image.
Entire Stack (docker)
Another option is to run the entire stack using the provided docker-compose file
: $ docker compose build && docker compose up -d
.
Entire Stack (non-docker)
Alternatively, you can also run $ make build-all-binaries
and $ make run-all-binaries
to run all the services together, then run $ make run-gateway
to start running the API Gateway, also.
Each service uses 'auto migrate' from the gorm library, which means any changes to database models are updated in the underlying tables automatically.
Connecting to the production database
Download CloudSQL Proxy from: https://cloud.google.com/sql/docs/mysql/connect-admin-proxy
Run it:
./cloud_sql_proxy -instances=mediamagic-core-ewanv:us-east4:mediamagic-dev-config-41b0c5b2=tcp:0.0.0.0:5432
Ask me for the database password.
The username is
mediamagic-dev-user
The database is specific to the service you want to connect to. Each microservice has its own database. The format is:
<service>_service
. For exampledeployment_service
.The schema is the name of the service, without
_service
. For example, the schema for the deployment service isdeployment
.The host is:
localhost:5432
as you're running the proxy locally.A connection string example:
postgresql://localhost:5432/deployment_service
A note on Authentication
Media Magic utilises Auth0 for authentication, and storing personal information about users. This is for security and compliance reasons, as well as a time saver in not implementing authentication ourselves.
To create a front-end or app that integrates into our Auth0, you will need the public token, which can be provided on request.
Tokens
User Token
There are two separate tokens in use with the Media Magic API's. The first is a short-lived user token, which Auth0 returns. Which expires after three days. This token should be used in mobile apps or web apps. This token should be used for basic actions needed by user interfaces.
The user token uses the following format: Authorization: Bearer <JWT>
.
API Keys
The second is a long-lived token, which is stateful and can be invalidated with immediate effect. This token should be used for programatic use-cases. For example, interacting with the rest API to perform automated tasks. For projects and integrations, you will probably need this token. It's advised to use this token where not for use in web apps, apps, or places where a user logs in via the Auth0 login prompt.
API Keys use the following format: x-mediamagic-key: <UUID>
.
API Keys
The second is a long-lived token, which is stateful and can be invalidated with immediate effect. This token should be used for programatic use-cases. For example, interacting with the rest API to perform automated tasks. For projects and integrations, you will probably need this token. It's advised to use this token where not for use in web apps, apps, or places where a user logs in via the Auth0 login prompt.
API Keys use the following format: x-mediamagic-key: <UUID>
.
Docs
You can find the full API documentation here: https://mediamagic.dev/docs
Below are some examples, but we would highly recommend using the docs ^
Bash commands
You can find the full bash documentation here: https://github.com/pingponglabs/mediamagic-platform/blob/main/models_management.md
Examples
For each of these examples, we're using the user or JWT token. But you can also use the API key:
x-mediamagic-key:<API_KEY>
Rather than:
Authorization:Bearer <JWT>
Authenticate
First we grab a generated login URL from the API. Open the link returned, this will take you through the user authentication process.
Once you've authenticated, a callback url will be called with an access token. Which is then validated and swapped for a user token.
$ curl -X GET https://mediamagic.dev/api/v1/auth/login -H 'content-type: application/mediamagic.rest.v1+json'
// Example output
// {"access_token":"<token>","refresh_token":"<refresh-token>","id_token":"","token_type":"Bearer"}
Now set your auth token as an environment variable for later use.
export TOKEN=<token>
Create an API Key
API keys are to be seen as long-lived API keys, to be used in other projects for example.
$ curl -X POST https://mediamagic.dev/api/v1/tokens \
-H 'Authorization: Bearer $USER_TOKEN' \
-H 'content-type: application/mediamagic.rest.v1+json'
-d '{ "name": "my-token" }'
Create a token for a team
$ curl -X POST https://mediamagic.dev/api/v1/tokens \
-H 'Authorization: Bearer $USER_TOKEN' \
-H 'content-type: application/mediamagic.rest.v1+json'
-d '{ "name": "my-token", "team_id": "<TEAM_ID>" }'
Create a team
$ curl -X POST https://mediamagic.dev/api/v1/tokens \
-H 'Authorization: Bearer $USER_TOKEN'
-H 'content-type: application/mediamagic.rest.v1_json'
-d '{ "name": "my-team" }'
Fetch Auth0 user metadata
first set your maintenance token as an environment variable for later use.
export MAINTENANCE_TOKEN=<maintenance-token>
Now establish the session by login into media-magic through auth-url API.
curl -X GET https://mediamagic.dev/api/v1/auth/login -H 'content-type: application/mediamagic.rest.v1+json'
curl --location --request GET 'https://mediamagic.dev/api/v1/fetch-metadata \
-header 'Cookie: auth_session=<session>' \
// Output Example
{
"email": "[email protected]",
"email_verified": false,
"username": "",
"phone_number": "",
"user_id": "auth0|6316dd611151a2dd290c2cca",
"created_at": "2022-09-06T05:40:49.848Z",
"updated_at": "2022-09-06T05:40:49.848Z",
"name": "[email protected]",
"nickname": "test76",
"picture": "https://s.gravatar.com/avatar/c7d2c798e44647ed1e62bdb5e2e57e99?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fte.png"
}
Media
Upload a Media asset
This endpoint is currently outside of the REST API as it deals with file uploads, so the headers etc are slightly different.
$ curl -X POST https://mediamagic.dev/uploads/upload -F '[email protected]' --header "Authorization: Bearer $ORG_TOKEN"
// {}
Upload media with tags
curl -X POST 'https://mediamagic.dev/uploads/upload' \
--header "Authorization: Bearer $TOKEN" \
--form '[email protected]' \
--form 'tags="hair,body,face"'
// Output example
{
"media": {
"id": "4bb25b57-0efe-11ed-8603-aea2f61b55d1",
"url": "https://cdn.mediamagic.dev/media/4bb25b57-0efe-11ed-8603-aea2f61b55d1.webp"
},
"base_url": "https://cdn.mediamagic.dev"
}
List media files
curl --location --request GET 'https://mediamagic.dev/api/v1/media' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"media": [
{
"id": "e8cc3bdb-0ca7-11ed-a94e-98fa9bf84765",
"image_name": "download.jpeg",
"media_key": "https://cdn.mediamagic.dev/media/e8cc3bdb-0ca7-11ed-a94e-98fa9bf84765.jpeg",
"status": "live",
"tags": [
"hair", "face"
],
"type": "source_asset",
"upload_date": "2022-07-26 11:28:03.259276 +0530 IST"
}
],
"media_key": "https://cdn.mediamagic.dev"
}
Filter media files by tags
curl --location --request GET 'https://mediamagic.dev/api/v1/media?tags=face' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"media": [
{
"id": "f5e14b6f-0ccb-11ed-b4c1-98fa9bf84765",
"image_name": "images.jpeg",
"media_key": "https://cdn.mediamagic.dev/media/f5e14b6f-0ccb-11ed-b4c1-98fa9bf84765.jpeg",
"status": "live",
"tags": [
"face",
"hair"
],
"type": "source_asset",
"upload_date": "2022-07-26 15:46:07.102843 +0530 IST"
}
],
"media_key": "https://cdn.mediamagic.dev"
}
Filter media files by exclude tags
curl --location --request GET 'https://mediamagic.dev/api/v1/media?excludeTags=face' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"media": [
{
"id": "3e822ca6-0ccc-11ed-b4c1-98fa9bf84765",
"image_name": "images.jpeg",
"media_key": "https://cdn.mediamagic.dev/media/3e822ca6-0ccc-11ed-b4c1-98fa9bf84765.jpeg",
"status": "live",
"tags": [
"hair"
],
"type": "source_asset",
"upload_date": "2022-07-26 15:48:08.702076 +0530 IST"
}
],
"media_key": "https://cdn.mediamagic.dev"
}
Filter media files by tags and exclude tags
curl --location --request GET 'https://mediamagic.dev/api/v1/media?tags=hair&excludeTags=body' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"media": [
{
"id": "3e822ca6-0ccc-11ed-b4c1-98fa9bf84765",
"image_name": "images.jpeg",
"media_key": "https://cdn.mediamagic.dev/media/3e822ca6-0ccc-11ed-b4c1-98fa9bf84765.jpeg",
"status": "live",
"tags": [
"hair"
],
"type": "source_asset",
"upload_date": "2022-07-26 15:48:08.702076 +0530 IST"
}
],
"media_key": "https://cdn.mediamagic.dev"
}
Update media files
curl --location --request PUT 'https://mediamagic.dev/api/v1/media/e8cc3bdb-0ca7-11ed-a94e-98fa9bf84765' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"tags": [
"face",
"tags",
"hair"
]
}'
// Output example
{
"media": {
"id": "e8cc3bdb-0ca7-11ed-a94e-98fa9bf84765",
"media_key": "media/e8cc3bdb-0ca7-11ed-a94e-98fa9bf84765.jpeg",
"status": "live",
"tags": [
"face",
"tags",
"hair"
],
"title": "media-upload"
},
"media_key": "https://cdn.mediamagic.dev"
}
Delete media files
curl --location --request DELETE 'https://mediamagic.dev/api/v1/media/4e06a91b-0cb7-11ed-b06e-98fa9bf84765' \
--header "Authorization: Bearer $TOKEN"
// Output example
Status - 204
Models
Create model with id
Creating a model requires a model name, a container name (which references a container on the cluster manager), and args.
Args are a list of arguments by name, the value for each name is metadata about that argument. There's a type
field, which is used to know what to replace the values with. For example, a file type fetches the file and replaces the placeholder with the full file route, assuming the value field is an image ID.
It's important to note that, currently, the args stored against each model, is used to describe what args need to be provided to the deployment. These are mostly for documentation purposes. There's no checks currently, eventually, the arguments included within a deployment, will be validated against the args defined on the model.
curl --location --request POST 'https://mediamagic.dev/api/v1/models' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"args": {
"input_image_file": {
"description": "changing the style of face component given a referrence",
"format": "--form input_image_file=@:value",
"type": "file"
}
},
"name": "Pixel+",
"version": "v0.1",
"container": "ubuntu",
"machine_type": "container1",
"machine_count": 2,
"tags": [
"image"
],
"black_icon": "https://cdn.mediamagic.dev/media/07ad8d37-3afd-11ed-af6c-e679ed67c206.png",
"white_icon": "https://cdn.mediamagic.dev/media/fa86e5c0-3afc-11ed-af6c-e679ed67c206.png",
"color_icon": "https://cdn.mediamagic.dev/media/18d41959-3afd-11ed-af6c-e679ed67c206.png",
"command": "127.0.0.1:8003/ESRGAN {args} --form Output_name=output",
"description": "esgran",
"id": "ab18c29c-19f9-4965-a005-fc5f56e2655b",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
]
}'
// Output example
{
"classification": "fast",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
],
"id": "ab18c29c-19f9-4965-a005-fc5f56e2655b",
"name": "Pixel+",
"version": "v0.1",
"tags": [
"image"
]
}
Create model without id or random id
curl --location --request POST 'https://mediamagic.dev/api/v1/models' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"args": {
"input_image_file": {
"description": "changing the style of face component given a referrence",
"format": "--form input_image_file=@:value",
"type": "file"
}
},
"name": "Pixel+",
"version": "v0.1",
"container": "ubuntu",
"machine_type": "container1",
"machine_count": 2,
"tags": [
"image"
],
"black_icon": "https://cdn.mediamagic.dev/media/07ad8d37-3afd-11ed-af6c-e679ed67c206.png",
"white_icon": "https://cdn.mediamagic.dev/media/fa86e5c0-3afc-11ed-af6c-e679ed67c206.png",
"color_icon": "https://cdn.mediamagic.dev/media/18d41959-3afd-11ed-af6c-e679ed67c206.png",
"command": "127.0.0.1:8003/ESRGAN {args} --form Output_name=output",
"description": "esgran",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
]
}'
// Output example
{
"classification": "fast",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
],
"id": "ab18c29c-19f9-4965-a005-fc5f56e2655b",
"name": "Pixel+",
"version": "v0.1",
"tags": [
"image"
]
}
Get model by id
curl --location --request GET 'https://mediamagic.dev/api/v1/models/ab18c29c-19f9-4965-a005-fc5f56e2655b' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"args": {
"input_image_file": {
"example": "",
"format": "--form input_image_file=@:value",
"optional": false,
"tags": null,
"type": "file"
}
},
"black_icon": "https://cdn.mediamagic.dev/media/07ad8d37-3afd-11ed-af6c-e679ed67c206.png",
"classification": "fast",
"color_icon": "https://cdn.mediamagic.dev/media/18d41959-3afd-11ed-af6c-e679ed67c206.png",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
],
"id": "ab18c29c-19f9-4965-a005-fc5f56e2655b",
"name": "Pixel+",
"version": "v0.1",
"run_count": 1,
"tags": [
"image"
],
"updated_at": "2022-09-23 09:30:10.160983 +0000 UTC",
"white_icon": "https://cdn.mediamagic.dev/media/fa86e5c0-3afc-11ed-af6c-e679ed67c206.png"
}
List models
curl --location --request GET 'https://mediamagic.dev/api/v1/models' \
--header "Authorization: Bearer $TOKEN"
// Output example
[ {
"args": {
"background": {
"example": "",
"format": "--form background=@:value",
"optional": false,
"tags": null,
"type": "file"
},
"base": {
"example": "",
"format": "--form base=@:value",
"optional": false,
"tags": null,
"type": "file"
},
"eyes": {
"example": "",
"format": "--form eyes=@:value",
"optional": false,
"tags": null,
"type": "file"
},
"hair": {
"example": "",
"format": "--form hair=@:value",
"optional": false,
"tags": null,
"type": "file"
},
"mouth": {
"example": "",
"format": "--form mouth=@:value",
"optional": false,
"tags": null,
"type": "file"
}
},
"black_icon": "https://cdn.mediamagic.dev/media/e1f22bf7-3afa-11ed-af6c-e679ed67c206.png",
"classification": "fast",
"color_icon": "https://cdn.mediamagic.dev/media/f2ea72f5-3afa-11ed-af6c-e679ed67c206.png",
"description": "changing the style of face component given a referrence",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
],
"id": "af4ab4d0-265d-4f68-86d6-3d9139cbb305",
"name": "StyleX",
"version": "v0.1",
"run_count": 1,
"tags": [
"face"
],
"updated_at": "2022-09-23 09:30:15.953259 +0000 UTC",
"white_icon": "https://cdn.mediamagic.dev/media/b7163eaf-3afa-11ed-af6c-e679ed67c206.png"
},
{
"args": {
"image": {
"example": "",
"format": "--form Image=@:value",
"optional": false,
"tags": null,
"type": "file"
},
"intensity": {
"example": "",
"format": "--form Intensity=:value",
"max": 1,
"min": 0,
"optional": false,
"tags": null,
"type": "array"
},
"model": {
"example": "",
"format": "--form Model=:value",
"optional": false,
"tags": null,
"type": "string"
},
"style": {
"example": "",
"format": "--form Style=@:value",
"optional": false,
"tags": null,
"type": "file"
}
},
"black_icon": "https://cdn.mediamagic.dev/media/8a0400e8-3afa-11ed-af6c-e679ed67c206.png",
"classification": "fast",
"color_icon": "https://cdn.mediamagic.dev/media/a35d9670-3afa-11ed-af6c-e679ed67c206.png",
"description": "sample swapx",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
],
"id": "9072b02e-3d6c-489d-9f2a-989f311b7934",
"name": "ColorX",
"version": "v0.1",
"run_count": 1,
"tags": [
"sky",
"tree",
"grass",
"landscape",
"building",
"swapping autoencoder"
],
"updated_at": "2022-09-23 09:30:17.391646 +0000 UTC",
"white_icon": "https://cdn.mediamagic.dev/media/60ab6254-3afa-11ed-af6c-e679ed67c206.png"
}
]
Filter models by tags
curl --location --request GET 'https://mediamagic.dev/api/v1/models?tags=tree' \
--header "Authorization: Bearer $TOKEN"
[
{
"args": {
"image": {
"example": "",
"format": "--form Image=@:value",
"optional": false,
"tags": null,
"type": "file"
},
"intensity": {
"example": "",
"format": "--form Intensity=:value",
"max": 1,
"min": 0,
"optional": false,
"tags": null,
"type": "array"
},
"model": {
"example": "",
"format": "--form Model=:value",
"optional": false,
"tags": null,
"type": "string"
},
"style": {
"example": "",
"format": "--form Style=@:value",
"optional": false,
"tags": null,
"type": "file"
}
},
"black_icon": "https://cdn.mediamagic.dev/media/8a0400e8-3afa-11ed-af6c-e679ed67c206.png",
"classification": "fast",
"color_icon": "https://cdn.mediamagic.dev/media/a35d9670-3afa-11ed-af6c-e679ed67c206.png",
"description": "sample swapx",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
],
"id": "9072b02e-3d6c-489d-9f2a-989f311b7934",
"name": "ColorX",
"version": "v0.1",
"run_count": 1,
"tags": [
"sky",
"tree",
"grass",
"landscape",
"building",
"swapping autoencoder"
],
"updated_at": "2022-09-23 09:30:17.391646 +0000 UTC",
"white_icon": "https://cdn.mediamagic.dev/media/60ab6254-3afa-11ed-af6c-e679ed67c206.png"
}
]
Update model
curl --location --request PUT 'https://mediamagic.dev/api/v1/models/1c3c27d8-5560-41d6-bb56-8c9c3be889c5' \
--header "Authorization: Bearer $TOKEN" \
--header 'Content-Type: application/json' \
--data-raw '{
"args": {
"input_image_file": {
"description": "changing the style of face component given a referrence",
"example": "",
"format": "--form input_image_file=@:value",
"optional": false,
"tags": null,
"type": "file"
}
},
"black_icon": "https://cdn.mediamagic.dev/media/07ad8d37-3afd-11ed-af6c-e679ed67c206.png",
"classification": "fast",
"color_icon": "https://cdn.mediamagic.dev/media/18d41959-3afd-11ed-af6c-e679ed67c206.png",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
],
"id": "ab18c29c-19f9-4965-a005-fc5f56e2655b",
"name": "Pixel+",
"version": "v0.1",
"tags": [
"image"
],
"updated_at": "2022-09-23 09:30:10.160983 +0000 UTC",
"white_icon": "https://cdn.mediamagic.dev/media/fa86e5c0-3afc-11ed-af6c-e679ed67c206.png"
}'
// Output example
{
"args": {
"input_image_file": {
"example": "",
"format": "--form input_image_file=@:value",
"optional": false,
"tags": null,
"type": "file"
}
},
"black_icon": "https://cdn.mediamagic.dev/media/07ad8d37-3afd-11ed-af6c-e679ed67c206.png",
"classification": "fast",
"color_icon": "https://cdn.mediamagic.dev/media/18d41959-3afd-11ed-af6c-e679ed67c206.png",
"example_outputs": [
"https://studio213.us/gpu/ai/input/em.jpg"
],
"id": "ab18c29c-19f9-4965-a005-fc5f56e2655b",
"name": "Pixel+",
"version": "v0.1",
"run_count": 1,
"tags": [
"image"
],
"updated_at": "2022-09-23 09:30:10.160983 +0000 UTC",
"white_icon": "https://cdn.mediamagic.dev/media/fa86e5c0-3afc-11ed-af6c-e679ed67c206.png"
}
Delete model
curl --location --request DELETE 'https://mediamagic.dev/api/v1/models/56c7c6bf-4987-4e36-9cc9-9281e96a7d74' \
--header "Authorization: Bearer $TOKEN"
// Output example
Status - 204
Like model
curl --location --request PATCH 'https://mediamagic.dev/api/v1/models/2a5b76a2-5a3c-4591-88dd-97ed8de5287c/like' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"message": "Model like successfully"
}
Unlike model
curl --location --request PATCH 'https://mediamagic.dev/api/v1/models/2a5b76a2-5a3c-4591-88dd-97ed8de5287c/unlike' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"message": "Model unlike successfully"
}
Follow model
curl --location --request PATCH 'https://mediamagic.dev/api/v1/models/2a5b76a2-5a3c-4591-88dd-97ed8de5287c/follow' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"message": "Model follow successfully"
}
Unfollow model
curl --location --request PATCH 'https://mediamagic.dev/api/v1/models/2a5b76a2-5a3c-4591-88dd-97ed8de5287c/unfollow' \
--header "Authorization: Bearer $TOKEN"
// Output example
{
"message": "Model unfollow successfully"
}
Create a Deployment
Valid types for args: int, float, string, file (file must be the UUID of an uploaded media asset).
$ curl -X POST --url
://mediamagic.dev/api/v1/deployments \
-H "Authorization: Bearer $TOKEN" \
-d '{ "name": "test", "model_id": "id", "args": { "source": "$(source)", "target": "$(target)" , "strength": 1 } }' \
-H 'content-type: application/mediamagic.rest.v1+json'
// Output example
// {"id":"c63dac60-451d-4697-a335-fcd7e6c676ea","model_id":"18bac45c-f799-4202-8517-297c6e5e4574","source_asset_id":"b8c662c8-95bd-44c0-aab3-77f33f6442dc","target_asset_id":"54c7064d-8020-4d6e-adff-2b04cc849d65"}
List Deployments
$ curl -X GET --url "https://mediamagic.dev/api/v1/deployments" \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/mediamagic.rest.v1+json'
List Jobs
$ curl -X GET --url "https://mediamagic.dev/api/v1/jobs" \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/mediamagic.rest.v1+json'
Get Job by ID
export ID=<id>
curl -X "GET" https://mediamagic.dev/api/v1/jobs/$ID \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/mediamagic.rest.v1+json'
Get Deployment by ID
export ID=<id>
curl -X "GET" https://mediamagic.dev/api/v1/deployments/$ID \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/mediamagic.rest.v1+json'
Get current billing usage
$ curl -X GET https://mediamagic.dev/api/v1/billing/usage \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/mediamagic.rest.v1+json'
Monitoring
Expose Grafana
export POD_NAME=(kubectl get pods --namespace default -l "app.kubernetes.io/name=grafana,app.kubernetes.io/instance=loki-grafana" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace default port-forward $POD_NAME 3000
Back-ups
Database
The Postgres database is backed up every day between 3-7am, 7 back-ups are kept, and point in time recovery is enabled also.
Disaster recovery - SQL
For full back-ups, see the Cloud SQL instance in Google Cloud.
Full database restore from back-up
Find the Cloud SQL instance in our Google Cloud account, this is named mediamagic-dev-db-41b0c5b2
currently.
Click into that database instance in the Google Cloud UI, then click on 'Export'. This will provide several options, including a 'Destination' section.
Select SQL, then select mediamagic-dev-db
from the 'Data to export' section.
A bucket has been created for database back-ups already, you will need to select that in the destination section, this is called backups-mm
.
This will export the entire database to that Cloud Storage bucket. You can download the file directly, or you can import it into another instance within Google Cloud.
Automated recovery
The database instance has point-in-time recovery enabled, with a 7 day tail.
You can find these under the 'Backups' menu item in the left-hand nav, when you navigate to the database instance in Google Cloud.
Last updated