Chapter 5. Enabling and using the Red Hat Quay API
By leveraging the Red Hat Quay API, you can streamline container registry management, automate tasks, and integrate Red Hat Quay’s functionalities into your existing workflow. This can improve efficiency, offer enhanced flexibility (by way of repository management, user management, user permissions, image management, and so on), increase the stability of your organization, repository, or overall deployment, and more.
The following sections explain how to enable and use the Red Hat Quay API.
5.1. Configuring Red Hat Quay to accept API calls
Prior to using the Red Hat Quay API, you must disable BROWSER_API_CALLS_XHR_ONLY
in your config.yaml
file. This allows you to avoid such errors as API calls must be invoked with an X-Requested-With header if called from a browser
.
Procedure
In your Red Hat Quay
config.yaml
file, setBROWSER_API_CALLS_XHR_ONLY
tofalse
. For example:# ... BROWSER_API_CALLS_XHR_ONLY: false # ...
- Restart your Red Hat Quay deployment.
5.2. Using the Red Hat Quay API
After you have created an application and generated an OAuth 2 access token with the desired settings, you can pass in the access token to GET
, PUT
, POST
, or DELETE
settings by using the API from the CLI. Generally, a Red Hat Quay API command looks similar to the following example:
$ curl -X GET -H "Authorization: Bearer <your_access_token>" 1 https://<quay-server.example.com>/api/v1/<example>/<endpoint>/ 2
All Red Hat Quay APIs are documented in the Application Programming Interface (API) chapter. Understanding how they are documented is crucial to successful invocation. Take, for example, the following entry for the createAppToken
API endpoint:
*createAppToken* 1 Create a new app specific token for user. 2 *POST /api/v1/user/apptoken* 3 **Authorizations: **oauth2_implicit (**user:admin**) 4 Request body schema (application/json) *Path parameters* 5 Name: **title** Description: Friendly name to help identify the token. Schema: string *Responses* 6 |HTTP Code|Description |Schema |201 |Successful creation | |400 |Bad Request |<<_apierror,ApiError>> |401 |Session required |<<_apierror,ApiError>> |403 |Unauthorized access |<<_apierror,ApiError>> |404 |Not found |<<_apierror,ApiError>> |===
- 1
- The name of the API endpoint.
- 2
- A brief description of the API endpoint.
- 3
- The API endpoint used for invocation.
- 4
- The authorizations required to use the API endpoint.
- 5
- The available paths to be used with the API endpoint. In this example,
title
is the only path to be used with thePOST /api/v1/user/apptoken
endpoint. - 6
- The API responses for this endpoint.
In order to use an API endpoint, you pass in your access token and then include the appropriate fields depending on your needs. The following procedure shows you how to use the POST /api/v1/user/apptoken
endpoint.
Prerequisites
- You have access to the Red Hat Quay API, which entails having already created an OAuth 2 access token.
-
You have set
BROWSER_API_CALLS_XHR_ONLY: false
in yourconfig.yaml
file.
Procedure
Create a user application by entering the
POST /api/v1/user/apptoken
API call:$ curl -X POST \ -H "Authorization: Bearer <access_token>" 1 -H "Content-Type: application/json" \ -d '{ "title": "MyAppToken" 2 }' \ "http://quay-server.example.com/api/v1/user/apptoken" 3
Example output
{"token": {"uuid": "6b5aa827-cee5-4fbe-a434-4b7b8a245ca7", "title": "MyAppToken", "last_accessed": null, "created": "Wed, 08 Jan 2025 19:32:48 -0000", "expiration": null, "token_code": "K2YQB1YO0ABYV5OBUYOMF9MCUABN12Y608Q9RHFXBI8K7IE8TYCI4WEEXSVH1AXWKZCKGUVA57PSA8N48PWED9F27PXATFUVUD9QDNCE9GOT9Q8ACYPIN0HL"}}
Verification
On the Red Hat Quay UI, click your username in the navigation pane
Account Settings. The name of your application appears under the Docker CLI and other Application Tokens heading. For example:
5.3. Automating Red Hat Quay processes by using the API
With the API, Red Hat Quay administrators and users with access to the API can automate repetitive tasks such as repository management or image pruning.
The following example shows you how you might use a Python script and a cron job to automate the deletion of OAuth 2 applications except the administrator’s token. This might be useful if you want to ensure an application associated with an OAuth 2 access token is cycled after a certain period of time.
Prerequisites
- You have access to the Red Hat Quay API, which entails having already created an OAuth 2 access token.
-
You have set
BROWSER_API_CALLS_XHR_ONLY: false
in yourconfig.yaml
file. -
You have installed the Python
requests
library using. - You have enabled cron jobs on your machine.
- You have created several organization applications, including one that will not be deleted.
Procedure
Create a Python script that executes an API command. The following example is used to delete organization applications using the
DELETE /api/v1/organization/{orgname}/applications/{client_id}
API endpoint.example.py file
import requests 1 # Hard-coded values API_BASE_URL = "http://<quay-server.example.com>/api/v1" 2 ACCESS_TOKEN = "<access_token>" 3 ORG_NAME = "<organization_name>" 4 def get_all_organization_applications(): url = f"{API_BASE_URL}/organization/{ORG_NAME}/applications" headers = { "Authorization": f"Bearer {ACCESS_TOKEN}" } response = requests.get(url, headers=headers) if response.status_code == 200: try: applications = response.json() # Print the raw response for debugging print("Raw response:", applications) # Adjust parsing logic based on the response structure if isinstance(applications, dict) and 'applications' in applications: applications = applications['applications'] if isinstance(applications, list): print("Organization applications retrieved successfully:") for app in applications: # Updated key from 'title' to 'name' print(f"Name: {app['name']}, Client ID: {app['client_id']}") return applications else: print("Unexpected response format.") return [] except requests.exceptions.JSONDecodeError: print("Error decoding JSON response:", response.text) return [] else: print(f"Failed to retrieve applications. Status code: {response.status_code}, Response: {response.text}") return [] def delete_organization_application(client_id): url = f"{API_BASE_URL}/organization/{ORG_NAME}/applications/{client_id}" headers = { "Authorization": f"Bearer {ACCESS_TOKEN}" } response = requests.delete(url, headers=headers) if response.status_code == 204: print(f"Application {client_id} deleted successfully.") else: print(f"Failed to delete application {client_id}. Status code: {response.status_code}, Response: {response.text}") def main(): applications = get_all_organization_applications() for app in applications: if app['name'] != "<admin_token_app>": <5> # Skip the "admin-token-app" delete_organization_application(app['client_id']) else: print(f"Skipping deletion of application: {app['name']}") # Execute the main function main()
-
Save the script as
prune_applications.py
. Create a cron job that automatically runs the script:
Open the crontab editor by running the following command:
$ crontab -e
In the editor, add the cron job for running the script. The following example runs the script once per month:
0 0 1 * * sudo python /path/to/prune_images.py >> /var/log/prune_images.log 2>&1