Podman API: Difference between revisions

From EDURange
Jump to navigationJump to search
No edit summary
No edit summary
Line 11: Line 11:
=== Config ===
=== Config ===


Configuration class that loads settings from environment variables. - MAX_WORKERS: Thread pool size (default: 10) - DEBUG: Enable debug mode (default: False) - REQUEST_TIMEOUT: Operation timeout in seconds (default: 30)
Configuration class that loads settings from environment variables.  
 
* - MAX_WORKERS: Thread pool size (default: 10)  
* - DEBUG: Enable debug mode (default: False)  
* - REQUEST_TIMEOUT: Operation timeout in seconds (default: 30)


<span id="custom-exceptions"></span>
<span id="custom-exceptions"></span>
== Custom Exceptions ==
== Custom Exceptions ==


'''PodmanAPIError(message, status_code=500)''' Custom exception for API errors with HTTP status codes.
'''PodmanAPIError(message, status_code=500)'''  
 
Custom exception for API errors with HTTP status codes.


<span id="decorators"></span>
<span id="decorators"></span>
== Decorators ==
== Decorators ==


'''@handle_errors''' Decorator that catches exceptions and converts them to PodmanAPIError: - Catches asyncio.TimeoutError → 408 Timeout - Catches “not found” errors → 404 Not Found - Catches other exceptions → 500 Internal Server Error
'''@handle_errors'''  
 
* Decorator that catches exceptions and converts them to PodmanAPIError:  
* - Catches asyncio.TimeoutError → 408 Timeout  
* - Catches “not found” errors → 404 Not Found  
* - Catches other exceptions → 500 Internal Server Error
 
'''@validate_json(required_fields=None)'''
 
Decorator that validates JSON request data:


'''@validate_json(required_fields=None)''' Decorator that validates JSON request data: - Ensures request contains valid JSON - Checks for required fields - Returns 400 Bad Request if validation fails
* - Ensures request contains valid JSON  
* - Checks for required fields  
* - Returns 400 Bad Request if validation fails


<span id="core-api-class"></span>
<span id="core-api-class"></span>
=== Core API Class ===
=== Core API Class ===


**PodmanAPI.__init__()** Initializes the API with a thread pool executor.
===== PodmanAPI.__init__() =====
Initializes the API with a thread pool executor.
 
 
'''PodmanAPI._get_client()'''
 
Returns a new Podman client instance.
 
 
'''PodmanAPI._run_async(func, timeout=30)'''
 
Executes a function asynchronously in the thread pool with timeout.


'''PodmanAPI._get_client()''' Returns a new Podman client instance.


'''PodmanAPI._run_async(func, timeout=30)''' Executes a function asynchronously in the thread pool with timeout.
'''PodmanAPI._handle_exec_result(result)'''  


'''PodmanAPI._handle_exec_result(result)''' Helper that normalizes exec_run results to (exit_code, output_string).
Helper that normalizes exec_run results to (exit_code, output_string).


<span id="container-management"></span>
<span id="container-management"></span>
== Container Management ==
== Container Management ==


'''create_container(config)''' Creates and starts a new container. - Input: {image, name, command?, environment?, ports?, volumes?, user?} - Returns: {id, name, status}
'''create_container(config)'''  
 
Creates and starts a new container.  
 
* - Input: {image, name, command?, environment?, ports?, volumes?, user?}  
* - Returns: {id, name, status}
 
 
'''start_container(name)'''


'''start_container(name)''' Starts an existing container. - Input: Container name - Returns: {name, status}
Starts an existing container.  


'''stop_container(name)''' Stops a running container. - Input: Container name - Returns: {name, status}
* - Input: Container name  
* - Returns: {name, status}


'''remove_container(name, force=False)''' Removes a container. - Input: Container name, force flag - Returns: {name, removed}


'''list_containers()''' Lists all containers (running and stopped). - Returns: Array of {id, name, status, image}
'''stop_container(name)'''  


'''get_container_logs(name, tail=100)''' Retrieves container logs. - Input: Container name, number of lines - Returns: {logs}
Stops a running container.  


Host Operations
* - Input: Container name
* - Returns: {name, status}


'''add_user(container_name, user_config)''' Creates a user inside a container. - Input: Container name, {username, password?, shell?} - Returns: {username, created}


'''add_file(container_name, file_config)''' Creates a file inside a container. - Input: Container name, {dest_path, content} - Returns: {dest_path, size}
'''remove_container(name, force=False)'''


'''execute_command(container_name, command, user=None)''' Executes a command inside a container. - Input: Container name, command string, optional user - Returns: {exit_code, output, success}
Removes a container.  


'''shutdown()''' Gracefully shuts down the thread pool executor.
* - Input: Container name, force flag
* - Returns: {name, removed}
 
 
'''list_containers()'''
 
Lists all containers (running and stopped).
 
* - Returns: Array of {id, name, status, image}
 
 
'''get_container_logs(name, tail=100)'''
 
Retrieves container logs.
 
* - Input: Container name, number of lines
* - Returns: {logs}
 
 
'''Host Operations'''
 
'''add_user(container_name, user_config)'''
 
Creates a user inside a container.
 
* - Input: Container name, {username, password?, shell?}
* - Returns: {username, created}
 
 
'''add_file(container_name, file_config)'''
 
Creates a file inside a container.
 
* - Input: Container name, {dest_path, content}
* - Returns: {dest_path, size}
 
'''execute_command(container_name, command, user=None)'''
 
Executes a command inside a container.
 
* - Input: Container name, command string, optional user
* - Returns: {exit_code, output, success}
 
 
'''shutdown()'''  
 
Gracefully shuts down the thread pool executor.


<span id="error-handlers"></span>
<span id="error-handlers"></span>
Line 71: Line 152:
== API Routes ==
== API Routes ==


'''POST /api/v1/containers''' Creates a new container. Requires image and name fields.
'''POST /api/v1/containers'''  
 
Creates a new container. Requires image and name fields.
 
 
'''POST /api/v1/containers/<name>/start'''
 
Starts the specified container.
 
 
'''POST /api/v1/containers/<name>/stop'''
 
Stops the specified container.
 
 
'''DELETE /api/v1/containers/<name>?force=bool'''
 
Removes the specified container. Optional force parameter.
 
 
'''GET /api/v1/containers'''
 
Lists all containers.
 
 
'''GET /api/v1/containers/<name>/logs?tail=int'''


'''POST /api/v1/containers/<name>/start''' Starts the specified container.
Gets container logs. Optional tail parameter (default: 100).


'''POST /api/v1/containers/<name>/stop''' Stops the specified container.


'''DELETE /api/v1/containers/<name>?force=bool''' Removes the specified container. Optional force parameter.
'''POST /api/v1/containers/<name>/users'''  


'''GET /api/v1/containers''' Lists all containers.
Adds a user to the container. Requires username field.


'''GET /api/v1/containers/<name>/logs?tail=int''' Gets container logs. Optional tail parameter (default: 100).


'''POST /api/v1/containers/<name>/users''' Adds a user to the container. Requires username field.
'''POST /api/v1/containers/<name>/files'''  


'''POST /api/v1/containers/<name>/files''' Adds a file to the container. Requires dest_path and content fields.
Adds a file to the container. Requires dest_path and content fields.


'''POST /api/v1/containers/<name>/exec''' Executes a command in the container. Requires command field.


'''GET /api/v1/health''' Health check endpoint. Returns Podman connection status.
'''POST /api/v1/containers/<name>/exec'''  


'''GET /api/v1/metrics''' Returns API metrics including uptime and thread pool status.
Executes a command in the container. Requires command field.
 
 
'''GET /api/v1/health'''
 
Health check endpoint. Returns Podman connection status.
 
 
'''GET /api/v1/metrics'''  
 
Returns API metrics including uptime and thread pool status.


<span id="signal-handlers"></span>
<span id="signal-handlers"></span>
== Signal Handlers ==
== Signal Handlers ==


'''shutdown_handler(sig, frame)''' Handles SIGINT and SIGTERM signals for graceful shutdown. - Logs signal details including source file and line number - Shuts down thread pool and exits cleanly
'''shutdown_handler(sig, frame)'''  
 
Handles SIGINT and SIGTERM signals for graceful shutdown.  
 
* - Logs signal details including source file and line number  
* - Shuts down thread pool and exits cleanly


<span id="response-format"></span>
<span id="response-format"></span>

Revision as of 13:37, 19 July 2025


More design thoughts and justifications to be added later, these are just the protocol specs.

This design is not meant to be followed, it's just my first sketch at listing everything we might need.

[TODO: Add the curl scripts I used for testing]

Configuration

Config

Configuration class that loads settings from environment variables.

  • - MAX_WORKERS: Thread pool size (default: 10)
  • - DEBUG: Enable debug mode (default: False)
  • - REQUEST_TIMEOUT: Operation timeout in seconds (default: 30)

Custom Exceptions

PodmanAPIError(message, status_code=500)

Custom exception for API errors with HTTP status codes.

Decorators

@handle_errors

  • Decorator that catches exceptions and converts them to PodmanAPIError:
  • - Catches asyncio.TimeoutError → 408 Timeout
  • - Catches “not found” errors → 404 Not Found
  • - Catches other exceptions → 500 Internal Server Error

@validate_json(required_fields=None)

Decorator that validates JSON request data:

  • - Ensures request contains valid JSON
  • - Checks for required fields
  • - Returns 400 Bad Request if validation fails

Core API Class

PodmanAPI.__init__()

Initializes the API with a thread pool executor.


PodmanAPI._get_client()

Returns a new Podman client instance.


PodmanAPI._run_async(func, timeout=30)

Executes a function asynchronously in the thread pool with timeout.


PodmanAPI._handle_exec_result(result)

Helper that normalizes exec_run results to (exit_code, output_string).

Container Management

create_container(config)

Creates and starts a new container.

  • - Input: {image, name, command?, environment?, ports?, volumes?, user?}
  • - Returns: {id, name, status}


start_container(name)

Starts an existing container.

  • - Input: Container name
  • - Returns: {name, status}


stop_container(name)

Stops a running container.

  • - Input: Container name
  • - Returns: {name, status}


remove_container(name, force=False)

Removes a container.

  • - Input: Container name, force flag
  • - Returns: {name, removed}


list_containers()

Lists all containers (running and stopped).

  • - Returns: Array of {id, name, status, image}


get_container_logs(name, tail=100)

Retrieves container logs.

  • - Input: Container name, number of lines
  • - Returns: {logs}


Host Operations

add_user(container_name, user_config)

Creates a user inside a container.

  • - Input: Container name, {username, password?, shell?}
  • - Returns: {username, created}


add_file(container_name, file_config)

Creates a file inside a container.

  • - Input: Container name, {dest_path, content}
  • - Returns: {dest_path, size}

execute_command(container_name, command, user=None)

Executes a command inside a container.

  • - Input: Container name, command string, optional user
  • - Returns: {exit_code, output, success}


shutdown()

Gracefully shuts down the thread pool executor.

Error Handlers

handle_podman_error(error) Flask error handler for PodmanAPIError exceptions. - Returns structured JSON error response with timestamp

handle_internal_error(error) Flask error handler for 500 Internal Server Error. - Logs error and returns generic error response

API Routes

POST /api/v1/containers

Creates a new container. Requires image and name fields.


POST /api/v1/containers/<name>/start

Starts the specified container.


POST /api/v1/containers/<name>/stop

Stops the specified container.


DELETE /api/v1/containers/<name>?force=bool

Removes the specified container. Optional force parameter.


GET /api/v1/containers

Lists all containers.


GET /api/v1/containers/<name>/logs?tail=int

Gets container logs. Optional tail parameter (default: 100).


POST /api/v1/containers/<name>/users

Adds a user to the container. Requires username field.


POST /api/v1/containers/<name>/files

Adds a file to the container. Requires dest_path and content fields.


POST /api/v1/containers/<name>/exec

Executes a command in the container. Requires command field.


GET /api/v1/health

Health check endpoint. Returns Podman connection status.


GET /api/v1/metrics

Returns API metrics including uptime and thread pool status.

Signal Handlers

shutdown_handler(sig, frame)

Handles SIGINT and SIGTERM signals for graceful shutdown.

  • - Logs signal details including source file and line number
  • - Shuts down thread pool and exits cleanly

Response Format

Successful requests will look like this:

{
  "success": true,
  "container|user|file|execution": { ... },
  "timestamp": "ISO-8601-timestamp"
}

Errors will look like this:

{
  "success": false,
  "error": {
    "message": "Error description",
    "code": 400,
    "type": "ErrorType"
  },
  "timestamp": "ISO-8601-timestamp"
}