diff --git a/src/api/http/src/handler/http/router/openapi.rs b/src/api/http/src/handler/http/router/openapi.rs index 50642abc05..6596f1f146 100644 --- a/src/api/http/src/handler/http/router/openapi.rs +++ b/src/api/http/src/handler/http/router/openapi.rs @@ -1267,6 +1267,7 @@ pub struct ApiDoc; openobserve_api_management::request::keys::delete_bulk, openobserve_api_management::request::license::get_license_info, openobserve_api_management::request::license::refresh_license_limits, + openobserve_api_management::request::license::rotate_license_key, openobserve_api_management::request::license::store_license, openobserve_api_management::request::oncall::acknowledge_response, openobserve_api_management::request::oncall::add_member, diff --git a/src/api/http/src/handler/http/router/openapi_coverage/mod.rs b/src/api/http/src/handler/http/router/openapi_coverage/mod.rs index f8e0220166..1d81e6e4da 100644 --- a/src/api/http/src/handler/http/router/openapi_coverage/mod.rs +++ b/src/api/http/src/handler/http/router/openapi_coverage/mod.rs @@ -99,7 +99,7 @@ const SUCCESS_CONTRACTS: &[ContractRow] = &[ "application/x-protobuf", "none", ), - ("ent", "POST", "/api/license/refresh", "200", JSON, "string"), + ("ent", "POST", "/api/license/refresh", "200", JSON, "object"), ( "all", "GET", diff --git a/src/api/management/src/request/license/mod.rs b/src/api/management/src/request/license/mod.rs index 1d21a6c77e..0d926b86a0 100644 --- a/src/api/management/src/request/license/mod.rs +++ b/src/api/management/src/request/license/mod.rs @@ -636,9 +636,13 @@ pub async fn get_license_info(Headers(email): Headers) -> Response { operation_id = "SaveLicense", summary = "Store a license key", security(("Authorization" = [])), + params( + ("dry_run" = Option, Query, description = "Check the key and answer 200 with a preview instead of storing it (default false)"), + ), request_body(content = inline(SaveLicenseRequest), content_type = "application/json"), responses( (status = 201, description = "Stored; the body is an empty JSON string", content_type = "application/json", body = String), + (status = 409, description = "A newer or conflicting key is already applied", content_type = "application/json", body = Object), ), extensions( ("x-o2-ratelimit" = json!({"module": "License", "operation": "create"})), @@ -716,7 +720,8 @@ pub async fn store_license( summary = "Refresh license limits", security(("Authorization" = [])), responses( - (status = 200, description = "Refreshed; the body is an empty JSON string", content_type = "application/json", body = String), + (status = 200, description = "Refreshed; the body reports the outcome", content_type = "application/json", body = Object), + (status = 409, description = "A license refresh is already running", content_type = "application/json", body = Object), ), extensions( ("x-o2-ratelimit" = json!({"module": "License", "operation": "update"})), @@ -736,6 +741,23 @@ pub async fn refresh_license_limits(Headers(user_email): Headers) -> ) } +#[utoipa::path( + post, + path = "/license/rotate_key", + context_path = "/api", + tag = "License", + operation_id = "RotateLicenseKey", + summary = "Rotate the instance key and refresh the license", + security(("Authorization" = [])), + responses( + (status = 200, description = "Rotated; the body reports the outcome", content_type = "application/json", body = Object), + (status = 409, description = "A license refresh is already running", content_type = "application/json", body = Object), + ), + extensions( + ("x-o2-ratelimit" = json!({"module": "License", "operation": "update"})), + ("x-o2-mcp" = json!({"enabled": false})) + ) +)] pub async fn rotate_license_key(Headers(user_email): Headers) -> Response { let email = user_email.user_id; if check_license_permission(&email, "PUT").await.is_err() {