Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ self-update = ["dep:self_update", "dep:semver"]
tui = ["dep:ratatui", "dep:crossterm", "dep:tui-textarea"]
webdav = [
"dep:dav-server",
"dep:axum",
"dep:tokio",
"dep:bytes",
"dep:futures",
]
Expand Down Expand Up @@ -69,10 +67,14 @@ rustic_core = { version = "0.11.0", features = ["cli"] }
jemallocator-global = { version = "0.3.2", optional = true }
mimalloc = { version = "0.1.48", default-features = false, optional = true }

# uuid
uuid = { version = "1", features = ["v4"] }

# webdav
axum = { version = "0.8.8", optional = true }
axum = { version = "0.8.8" }
dav-server = { version = "0.11.0", default-features = false, optional = true }
tokio = { version = "1", optional = true }
tokio = { version = "1" }
utoipa = { version = "5" }

# tui
crossterm = { version = "0.28", optional = true }
Expand Down
11 changes: 11 additions & 0 deletions docs/Readme.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# Documentation

Our documentation can be found at: <https://rustic.cli.rs/docs>

## Generate OpenAPI Schema

You can generate the HTTP API OpenAPI schema directly from code and write it under
`docs/` with:

```bash
cargo run -- serve --openapi-output docs/openapi.json
```

This command serializes `ApiDoc::openapi()` and exits without starting the server.
219 changes: 219 additions & 0 deletions docs/openapi.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
{
"openapi": "3.1.0",
"info": {
"title": "rustic-rs",
"description": "rustic - fast, encrypted, deduplicated backups powered by Rust\n",
"contact": {
"name": "the rustic-rs team"
},
"license": {
"name": "Apache-2.0 OR MIT",
"identifier": "Apache-2.0 OR MIT"
},
"version": "0.11.2"
},
"paths": {
"/backup": {
"post": {
"tags": [
"rustic-api"
],
"summary": "Respond to /backup endpoint, used for starting backup jobs.",
"description": "Development note: test this with:\n\ncurl -i -X POST http://localhost:8080/backup -H \"Content-Type: application/json\" -d @tests/http-server/backup-request.json\n\n# Returns\n\nReturns BackupStartResponse in case of success",
"operationId": "start_backup",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BackupStartRequest"
}
}
},
"required": true
},
"responses": {
"202": {
"description": "Backup job accepted",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BackupStartResponse"
}
}
}
},
"400": {
"description": "Invalid request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ApiErrorResponse"
}
}
}
},
"409": {
"description": "A backup job is already running",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ApiErrorResponse"
}
}
}
},
"500": {
"description": "Internal error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ApiErrorResponse"
}
}
}
}
}
}
},
"/backup/{job_id}": {
"get": {
"tags": [
"rustic-api"
],
"summary": "Get the status of a backup job.",
"description": "Development note: test this with:\n\ncurl -i -X GET http://localhost:8080/backup/<job_id>",
"operationId": "get_backup_status",
"parameters": [
{
"name": "job_id",
"in": "path",
"description": "Job identifier returned by POST /backup",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Job status",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BackupJobStatusResponse"
}
}
}
},
"404": {
"description": "Job not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ApiErrorResponse"
}
}
}
}
}
}
},
"/health": {
"get": {
"tags": [
"rustic-api"
],
"summary": "Respond to /health endpoint, used for health checks and testing connectivity to the API.",
"description": "Development note: test this with:\n\ncurl -i -X GET http://localhost:8080/health\n\n# Returns\n\nReturns \"ok\" if the API is running.",
"operationId": "health",
"responses": {
"200": {
"description": "API is running",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"ApiErrorResponse": {
"type": "object",
"description": "API error payload.",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
},
"BackupJobStatusResponse": {
"type": "object",
"description": "Response body for GET /backup/{job_id}.",
"required": [
"job-id",
"status"
],
"properties": {
"job-id": {
"type": "string",
"description": "The job identifier."
},
"status": {
"$ref": "#/components/schemas/JobStatus",
"description": "Current status of the job."
}
}
},
"BackupStartRequest": {
"type": "object",
"description": "Request payload for creating a backup job.",
"properties": {
"profile-name": {
"type": [
"string",
"null"
],
"description": "Optional profile name to define which sources to backup\nEquivalent to the --name CLI option of \"backup\" command."
}
}
},
"BackupStartResponse": {
"type": "object",
"description": "API response returned when a backup job has been accepted.",
"required": [
"job-id"
],
"properties": {
"job-id": {
"type": "string",
"description": "Unique identifier for the backup job.\nPlease note that at this time rustic can only run one backup job at a time,\nso that there will be at most one active job_id.\nThis parameter allows the API to be extended in the future to support multiple concurrent jobs if needed."
}
}
},
"JobStatus": {
"type": "string",
"description": "Status of a backup job.",
"enum": [
"running",
"completed",
"failed"
]
}
}
},
"tags": [
{
"name": "rustic-api",
"description": "Rustic HTTP API skeleton"
}
]
}
6 changes: 6 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub(crate) mod repair;
pub(crate) mod repoinfo;
pub(crate) mod restore;
pub(crate) mod rewrite;
pub(crate) mod serve;
pub(crate) mod self_update;
pub(crate) mod show_config;
pub(crate) mod snapshots;
Expand All @@ -39,6 +40,7 @@ use std::sync::mpsc::channel;

#[cfg(feature = "mount")]
use crate::commands::mount::MountCmd;
use crate::commands::serve::ServeCmd;
#[cfg(feature = "webdav")]
use crate::commands::webdav::WebDavCmd;
use crate::{
Expand Down Expand Up @@ -144,6 +146,9 @@ enum RusticCmd {
/// Rewrite existing snapshot(s)
Rewrite(Box<RewriteCmd>),

/// Start the rustic HTTP API server
Serve(Box<ServeCmd>),

/// Repair a snapshot or the repository index
Repair(Box<RepairCmd>),

Expand Down Expand Up @@ -296,6 +301,7 @@ impl Configurable<RusticConfig> for EntryPoint {
RusticCmd::Webdav(cmd) => cmd.override_config(config),
#[cfg(feature = "mount")]
RusticCmd::Mount(cmd) => cmd.override_config(config),
RusticCmd::Serve(cmd) => cmd.override_config(config),

// subcommands that don't need special overrides use a catch all
_ => Ok(config),
Expand Down
Loading