diff --git a/services/api-server/VERSION b/services/api-server/VERSION index a918a2aa18d5..faef31a4357c 100644 --- a/services/api-server/VERSION +++ b/services/api-server/VERSION @@ -1 +1 @@ -0.6.0 +0.7.0 diff --git a/services/api-server/openapi.json b/services/api-server/openapi.json index 8ade6cff6147..7965ae507f20 100644 --- a/services/api-server/openapi.json +++ b/services/api-server/openapi.json @@ -3,7 +3,7 @@ "info": { "title": "osparc.io public API", "description": "osparc-simcore public API specifications", - "version": "0.6.0" + "version": "0.7.0" }, "paths": { "/v0/meta": { @@ -1869,13 +1869,132 @@ ] } }, + "/v0/solvers/{solver_key}/releases/{version}/pricing_plan": { + "get": { + "tags": [ + "solvers" + ], + "summary": "Get Solver Pricing Plan", + "description": "Gets solver pricing plan\n\nNew in *version 0.7*", + "operationId": "get_solver_pricing_plan", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "pattern": "^simcore/services/comp/([a-z0-9][a-z0-9_.-]*/)*([a-z0-9-_]+[a-z0-9])$", + "title": "Solver Key" + }, + "name": "solver_key", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){2}(-(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*)(\\.(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*))*)?(\\+[-\\da-zA-Z]+(\\.[-\\da-zA-Z-]+)*)?$", + "title": "Version" + }, + "name": "version", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServicePricingPlanGet" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "429": { + "description": "Too many requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "502": { + "description": "Unexpected error when communicating with backend service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "503": { + "description": "Service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "504": { + "description": "Request to a backend service timed out.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, "/v0/solvers/{solver_key}/releases/{version}/jobs": { "get": { "tags": [ "solvers" ], "summary": "List Jobs", - "description": "List of jobs in a specific released solver (limited to 20 jobs)\n\nSEE `get_jobs_page` for paginated version of this function", + "description": "List of jobs in a specific released solver (limited to 20 jobs)\n\n- DEPRECATION: This implementation and returned values are deprecated and the will be replaced by that of get_jobs_page\n- SEE `get_jobs_page` for paginated version of this function", "operationId": "list_jobs", "parameters": [ { @@ -2169,14 +2288,14 @@ ] } }, - "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}:start": { - "post": { + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}": { + "get": { "tags": [ "solvers" ], - "summary": "Start Job", - "description": "Starts job job_id created with the solver solver_key:version\n\nAdded in *version 0.4.3*: query parameter `cluster_id`\nAdded in *version 0.6*: responds with a 202 when successfully starting a computation", - "operationId": "start_job", + "summary": "Get Job", + "description": "Gets job of a given solver", + "operationId": "get_job", "parameters": [ { "required": true, @@ -2207,25 +2326,15 @@ }, "name": "job_id", "in": "path" - }, - { - "required": false, - "schema": { - "type": "integer", - "minimum": 0, - "title": "Cluster Id" - }, - "name": "cluster_id", - "in": "query" } ], "responses": { - "202": { + "200": { "description": "Successful Response", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/JobStatus" + "$ref": "#/components/schemas/Job" } } } @@ -2300,32 +2409,12 @@ } } }, - "200": { - "description": "Job already started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JobStatus" - } - } - } - }, - "406": { - "description": "Cluster not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorGet" - } - } - } - }, "422": { - "description": "Configuration error", + "description": "Validation Error", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorGet" + "$ref": "#/components/schemas/HTTPValidationError" } } } @@ -2336,15 +2425,14 @@ "HTTPBasic": [] } ] - } - }, - "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}:stop": { - "post": { + }, + "delete": { "tags": [ "solvers" ], - "summary": "Stop Job", - "operationId": "stop_job", + "summary": "Delete Job", + "description": "Deletes an existing solver job\n\nNew in *version 0.7*", + "operationId": "delete_job", "parameters": [ { "required": true, @@ -2378,15 +2466,8 @@ } ], "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JobStatus" - } - } - } + "204": { + "description": "Successful Response" }, "402": { "description": "Payment required", @@ -2476,13 +2557,14 @@ ] } }, - "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}:inspect": { + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}:start": { "post": { "tags": [ "solvers" ], - "summary": "Inspect Job", - "operationId": "inspect_job", + "summary": "Start Job", + "description": "Starts job job_id created with the solver solver_key:version\n\nAdded in *version 0.4.3*: query parameter `cluster_id`\nAdded in *version 0.6*: responds with a 202 when successfully starting a computation", + "operationId": "start_job", "parameters": [ { "required": true, @@ -2513,10 +2595,20 @@ }, "name": "job_id", "in": "path" + }, + { + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "title": "Cluster Id" + }, + "name": "cluster_id", + "in": "query" } ], "responses": { - "200": { + "202": { "description": "Successful Response", "content": { "application/json": { @@ -2596,12 +2688,32 @@ } } }, + "200": { + "description": "Job already started", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobStatus" + } + } + } + }, + "406": { + "description": "Cluster not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, "422": { - "description": "Validation Error", + "description": "Configuration error", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/ErrorGet" } } } @@ -2614,14 +2726,13 @@ ] } }, - "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}": { - "get": { + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}:stop": { + "post": { "tags": [ "solvers" ], - "summary": "Get Job", - "description": "Gets job of a given solver", - "operationId": "get_job", + "summary": "Stop Job", + "operationId": "stop_job", "parameters": [ { "required": true, @@ -2660,7 +2771,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Job" + "$ref": "#/components/schemas/JobStatus" } } } @@ -2753,13 +2864,13 @@ ] } }, - "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/outputs": { - "get": { + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}:inspect": { + "post": { "tags": [ "solvers" ], - "summary": "Get Job Outputs", - "operationId": "get_job_outputs", + "summary": "Inspect Job", + "operationId": "inspect_job", "parameters": [ { "required": true, @@ -2798,7 +2909,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/JobOutputs" + "$ref": "#/components/schemas/JobStatus" } } } @@ -2814,7 +2925,7 @@ } }, "404": { - "description": "Job not found", + "description": "Job/wallet/pricing details not found", "content": { "application/json": { "schema": { @@ -2891,14 +3002,14 @@ ] } }, - "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/outputs/logfile": { + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/metadata": { "get": { "tags": [ "solvers" ], - "summary": "Get Job Output Logfile", - "description": "Special extra output with persistent logs file for the solver run.\n\n**NOTE**: this is not a log stream but a predefined output that is only\navailable after the job is done.\n\nNew in *version 0.4.0*", - "operationId": "get_job_output_logfile", + "summary": "Get Job Custom Metadata", + "description": "Gets custom metadata from a job\n\nNew in *version 0.7*", + "operationId": "get_job_custom_metadata", "parameters": [ { "required": true, @@ -2932,33 +3043,25 @@ } ], "responses": { - "307": { - "description": "Successful Response" - }, "200": { - "description": "Returns a log file", + "description": "Successful Response", "content": { - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - }, - "application/zip": { - "schema": { - "type": "string", - "format": "binary" - } - }, - "text/plain": { + "application/json": { "schema": { - "type": "string" + "$ref": "#/components/schemas/JobMetadata" } } } }, "404": { - "description": "Log not found" + "description": "Metadata not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } }, "429": { "description": "Too many requests", @@ -3026,15 +3129,14 @@ "HTTPBasic": [] } ] - } - }, - "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/logstream": { - "get": { + }, + "patch": { "tags": [ "solvers" ], - "summary": "Get Log Stream", - "operationId": "get_log_stream", + "summary": "Replace Job Custom Metadata", + "description": "Updates custom metadata from a job\n\nNew in *version 0.7*", + "operationId": "replace_job_custom_metadata", "parameters": [ { "required": true, @@ -3067,30 +3169,31 @@ "in": "path" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobMetadataUpdate" + } + } + }, + "required": true + }, "responses": { "200": { - "description": "Returns a JobLog or an ErrorGet", + "description": "Successful Response", "content": { - "application/x-ndjson": { + "application/json": { "schema": { - "anyOf": [ - { - "$ref": "#/components/schemas/JobLog" - }, - { - "$ref": "#/components/schemas/ErrorGet" - } - ], - "type": "string", - "title": "Response 200 Get Log Stream V0 Solvers Solver Key Releases Version Jobs Job Id Logstream Get" + "$ref": "#/components/schemas/JobMetadata" } } } }, - "409": { - "description": "Conflict: Logs are already being streamed", + "404": { + "description": "Metadata not found", "content": { - "application/x-ndjson": { + "application/json": { "schema": { "$ref": "#/components/schemas/ErrorGet" } @@ -3100,7 +3203,7 @@ "429": { "description": "Too many requests", "content": { - "application/x-ndjson": { + "application/json": { "schema": { "$ref": "#/components/schemas/ErrorGet" } @@ -3110,7 +3213,7 @@ "500": { "description": "Internal server error", "content": { - "application/x-ndjson": { + "application/json": { "schema": { "$ref": "#/components/schemas/ErrorGet" } @@ -3120,7 +3223,7 @@ "502": { "description": "Unexpected error when communicating with backend service", "content": { - "application/x-ndjson": { + "application/json": { "schema": { "$ref": "#/components/schemas/ErrorGet" } @@ -3130,7 +3233,7 @@ "503": { "description": "Service unavailable", "content": { - "application/x-ndjson": { + "application/json": { "schema": { "$ref": "#/components/schemas/ErrorGet" } @@ -3140,7 +3243,7 @@ "504": { "description": "Request to a backend service timed out.", "content": { - "application/x-ndjson": { + "application/json": { "schema": { "$ref": "#/components/schemas/ErrorGet" } @@ -3165,15 +3268,35 @@ ] } }, - "/v0/studies": { + "/v0/solvers/{solver_key}/releases/{version}/jobs/page": { "get": { "tags": [ - "studies" + "solvers" ], - "summary": "List Studies", - "description": "New in *version 0.5.0*", - "operationId": "list_studies", + "summary": "Get Jobs Page", + "description": "List of jobs on a specific released solver (includes pagination)\n\nNew in *version 0.7*", + "operationId": "get_jobs_page", "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "pattern": "^simcore/services/comp/([a-z0-9][a-z0-9_.-]*/)*([a-z0-9-_]+[a-z0-9])$", + "title": "Solver Key" + }, + "name": "solver_key", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){2}(-(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*)(\\.(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*))*)?(\\+[-\\da-zA-Z]+(\\.[-\\da-zA-Z-]+)*)?$", + "title": "Version" + }, + "name": "version", + "in": "path" + }, { "required": false, "schema": { @@ -3204,62 +3327,33 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Page_Study_" + "$ref": "#/components/schemas/Page_Job_" } } } }, - "422": { - "description": "Validation Error", + "402": { + "description": "Payment required", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/ErrorGet" } } } - } - }, - "security": [ - { - "HTTPBasic": [] - } - ] - } - }, - "/v0/studies/{study_id}": { - "get": { - "tags": [ - "studies" - ], - "summary": "Get Study", - "description": "New in *version 0.5.0*", - "operationId": "get_study", - "parameters": [ - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Study Id" - }, - "name": "study_id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Successful Response", + }, + "404": { + "description": "Job/wallet/pricing details not found", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Study" + "$ref": "#/components/schemas/ErrorGet" } } } }, - "404": { - "description": "Study not found", + "429": { + "description": "Too many requests", "content": { "application/json": { "schema": { @@ -3268,76 +3362,38 @@ } } }, - "422": { - "description": "Validation Error", + "500": { + "description": "Internal server error", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/ErrorGet" } } } - } - }, - "security": [ - { - "HTTPBasic": [] - } - ] - } - }, - "/v0/studies/{study_id}:clone": { - "post": { - "tags": [ - "studies" - ], - "summary": "Clone Study", - "operationId": "clone_study", - "parameters": [ - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Study Id" - }, - "name": "study_id", - "in": "path" }, - { - "required": false, - "schema": { - "type": "string", - "format": "uuid", - "title": "X-Simcore-Parent-Project-Uuid" - }, - "name": "x-simcore-parent-project-uuid", - "in": "header" + "502": { + "description": "Unexpected error when communicating with backend service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } }, - { - "required": false, - "schema": { - "type": "string", - "format": "uuid", - "title": "X-Simcore-Parent-Node-Id" - }, - "name": "x-simcore-parent-node-id", - "in": "header" - } - ], - "responses": { - "201": { - "description": "Successful Response", + "503": { + "description": "Service unavailable", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Study" + "$ref": "#/components/schemas/ErrorGet" } } } }, - "404": { - "description": "Study not found", + "504": { + "description": "Request to a backend service timed out.", "content": { "application/json": { "schema": { @@ -3364,23 +3420,42 @@ ] } }, - "/v0/studies/{study_id}/ports": { + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/outputs": { "get": { "tags": [ - "studies" + "solvers" ], - "summary": "List Study Ports", - "description": "Lists metadata on ports of a given study\n\nNew in *version 0.5.0*", - "operationId": "list_study_ports", + "summary": "Get Job Outputs", + "operationId": "get_job_outputs", "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "pattern": "^simcore/services/comp/([a-z0-9][a-z0-9_.-]*/)*([a-z0-9-_]+[a-z0-9])$", + "title": "Solver Key" + }, + "name": "solver_key", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){2}(-(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*)(\\.(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*))*)?(\\+[-\\da-zA-Z]+(\\.[-\\da-zA-Z-]+)*)?$", + "title": "Version" + }, + "name": "version", + "in": "path" + }, { "required": true, "schema": { "type": "string", "format": "uuid", - "title": "Study Id" + "title": "Job Id" }, - "name": "study_id", + "name": "job_id", "in": "path" } ], @@ -3390,13 +3465,13 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OnePage_StudyPort_" + "$ref": "#/components/schemas/JobOutputs" } } } }, - "404": { - "description": "Study not found", + "402": { + "description": "Payment required", "content": { "application/json": { "schema": { @@ -3405,9 +3480,1237 @@ } } }, - "422": { - "description": "Validation Error", - "content": { + "404": { + "description": "Job not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "429": { + "description": "Too many requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "502": { + "description": "Unexpected error when communicating with backend service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "503": { + "description": "Service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "504": { + "description": "Request to a backend service timed out.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/outputs/logfile": { + "get": { + "tags": [ + "solvers" + ], + "summary": "Get Job Output Logfile", + "description": "Special extra output with persistent logs file for the solver run.\n\n**NOTE**: this is not a log stream but a predefined output that is only\navailable after the job is done.\n\nNew in *version 0.4.0*", + "operationId": "get_job_output_logfile", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "pattern": "^simcore/services/comp/([a-z0-9][a-z0-9_.-]*/)*([a-z0-9-_]+[a-z0-9])$", + "title": "Solver Key" + }, + "name": "solver_key", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){2}(-(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*)(\\.(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*))*)?(\\+[-\\da-zA-Z]+(\\.[-\\da-zA-Z-]+)*)?$", + "title": "Version" + }, + "name": "version", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + } + ], + "responses": { + "307": { + "description": "Successful Response" + }, + "200": { + "description": "Returns a log file", + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "application/zip": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Log not found" + }, + "429": { + "description": "Too many requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "502": { + "description": "Unexpected error when communicating with backend service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "503": { + "description": "Service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "504": { + "description": "Request to a backend service timed out.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/wallet": { + "get": { + "tags": [ + "solvers" + ], + "summary": "Get Job Wallet", + "description": "Get job wallet\n\nNew in *version 0.7*", + "operationId": "get_job_wallet", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "pattern": "^simcore/services/comp/([a-z0-9][a-z0-9_.-]*/)*([a-z0-9-_]+[a-z0-9])$", + "title": "Solver Key" + }, + "name": "solver_key", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){2}(-(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*)(\\.(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*))*)?(\\+[-\\da-zA-Z]+(\\.[-\\da-zA-Z-]+)*)?$", + "title": "Version" + }, + "name": "version", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WalletGetWithAvailableCredits" + } + } + } + }, + "404": { + "description": "Wallet not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "403": { + "description": "Access to wallet is not allowed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "429": { + "description": "Too many requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "502": { + "description": "Unexpected error when communicating with backend service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "503": { + "description": "Service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "504": { + "description": "Request to a backend service timed out.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/pricing_unit": { + "get": { + "tags": [ + "solvers" + ], + "summary": "Get Job Pricing Unit", + "description": "Get job pricing unit\n\nNew in *version 0.7*", + "operationId": "get_job_pricing_unit", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "pattern": "^simcore/services/comp/([a-z0-9][a-z0-9_.-]*/)*([a-z0-9-_]+[a-z0-9])$", + "title": "Solver Key" + }, + "name": "solver_key", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){2}(-(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*)(\\.(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*))*)?(\\+[-\\da-zA-Z]+(\\.[-\\da-zA-Z-]+)*)?$", + "title": "Version" + }, + "name": "version", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PricingUnitGet" + } + } + } + }, + "404": { + "description": "Pricing unit not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "429": { + "description": "Too many requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "502": { + "description": "Unexpected error when communicating with backend service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "503": { + "description": "Service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "504": { + "description": "Request to a backend service timed out.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/solvers/{solver_key}/releases/{version}/jobs/{job_id}/logstream": { + "get": { + "tags": [ + "solvers" + ], + "summary": "Get Log Stream", + "operationId": "get_log_stream", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "pattern": "^simcore/services/comp/([a-z0-9][a-z0-9_.-]*/)*([a-z0-9-_]+[a-z0-9])$", + "title": "Solver Key" + }, + "name": "solver_key", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "pattern": "^(0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){2}(-(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*)(\\.(0|[1-9]\\d*|\\d*[-a-zA-Z][-\\da-zA-Z]*))*)?(\\+[-\\da-zA-Z]+(\\.[-\\da-zA-Z-]+)*)?$", + "title": "Version" + }, + "name": "version", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Returns a JobLog or an ErrorGet", + "content": { + "application/x-ndjson": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/JobLog" + }, + { + "$ref": "#/components/schemas/ErrorGet" + } + ], + "type": "string", + "title": "Response 200 Get Log Stream V0 Solvers Solver Key Releases Version Jobs Job Id Logstream Get" + } + } + } + }, + "409": { + "description": "Conflict: Logs are already being streamed", + "content": { + "application/x-ndjson": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "429": { + "description": "Too many requests", + "content": { + "application/x-ndjson": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/x-ndjson": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "502": { + "description": "Unexpected error when communicating with backend service", + "content": { + "application/x-ndjson": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "503": { + "description": "Service unavailable", + "content": { + "application/x-ndjson": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "504": { + "description": "Request to a backend service timed out.", + "content": { + "application/x-ndjson": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies": { + "get": { + "tags": [ + "studies" + ], + "summary": "List Studies", + "description": "New in *version 0.5.0*", + "operationId": "list_studies", + "parameters": [ + { + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "title": "Limit", + "default": 50 + }, + "name": "limit", + "in": "query" + }, + { + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "title": "Offset", + "default": 0 + }, + "name": "offset", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Page_Study_" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}": { + "get": { + "tags": [ + "studies" + ], + "summary": "Get Study", + "description": "New in *version 0.5.0*", + "operationId": "get_study", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Study" + } + } + } + }, + "404": { + "description": "Study not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}:clone": { + "post": { + "tags": [ + "studies" + ], + "summary": "Clone Study", + "operationId": "clone_study", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + }, + { + "required": false, + "schema": { + "type": "string", + "format": "uuid", + "title": "X-Simcore-Parent-Project-Uuid" + }, + "name": "x-simcore-parent-project-uuid", + "in": "header" + }, + { + "required": false, + "schema": { + "type": "string", + "format": "uuid", + "title": "X-Simcore-Parent-Node-Id" + }, + "name": "x-simcore-parent-node-id", + "in": "header" + } + ], + "responses": { + "201": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Study" + } + } + } + }, + "404": { + "description": "Study not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}/ports": { + "get": { + "tags": [ + "studies" + ], + "summary": "List Study Ports", + "description": "Lists metadata on ports of a given study\n\nNew in *version 0.5.0*", + "operationId": "list_study_ports", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OnePage_StudyPort_" + } + } + } + }, + "404": { + "description": "Study not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}/jobs": { + "post": { + "tags": [ + "studies" + ], + "summary": "Create Study Job", + "description": "hidden -- if True (default) hides project from UI", + "operationId": "create_study_job", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + }, + { + "required": false, + "schema": { + "type": "boolean", + "title": "Hidden", + "default": true + }, + "name": "hidden", + "in": "query" + }, + { + "required": false, + "schema": { + "type": "string", + "format": "uuid", + "title": "X-Simcore-Parent-Project-Uuid" + }, + "name": "x-simcore-parent-project-uuid", + "in": "header" + }, + { + "required": false, + "schema": { + "type": "string", + "format": "uuid", + "title": "X-Simcore-Parent-Node-Id" + }, + "name": "x-simcore-parent-node-id", + "in": "header" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobInputs" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Job" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}/jobs/{job_id}": { + "delete": { + "tags": [ + "studies" + ], + "summary": "Delete Study Job", + "description": "Deletes an existing study job", + "operationId": "delete_study_job", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}/jobs/{job_id}:start": { + "post": { + "tags": [ + "studies" + ], + "summary": "Start Study Job", + "description": "Changed in *version 0.6.0*: Now responds with a 202 when successfully starting a computation", + "operationId": "start_study_job", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + }, + { + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "title": "Cluster Id" + }, + "name": "cluster_id", + "in": "query" + } + ], + "responses": { + "202": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobStatus" + } + } + } + }, + "402": { + "description": "Payment required", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "404": { + "description": "Job/wallet/pricing details not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "429": { + "description": "Too many requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "502": { + "description": "Unexpected error when communicating with backend service", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "503": { + "description": "Service unavailable", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "504": { + "description": "Request to a backend service timed out.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "200": { + "description": "Job already started", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobStatus" + } + } + } + }, + "406": { + "description": "Cluster not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "422": { + "description": "Configuration error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}/jobs/{job_id}:stop": { + "post": { + "tags": [ + "studies" + ], + "summary": "Stop Study Job", + "operationId": "stop_study_job", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobStatus" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" @@ -3423,14 +4726,129 @@ ] } }, - "/v0/studies/{study_id}/jobs": { + "/v0/studies/{study_id}/jobs/{job_id}:inspect": { + "post": { + "tags": [ + "studies" + ], + "summary": "Inspect Study Job", + "operationId": "inspect_study_job", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobStatus" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}/jobs/{job_id}/outputs": { "post": { "tags": [ "studies" ], - "summary": "Create Study Job", - "description": "hidden -- if True (default) hides project from UI", - "operationId": "create_study_job", + "summary": "Get Study Job Outputs", + "operationId": "get_study_job_outputs", + "parameters": [ + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Study Id" + }, + "name": "study_id", + "in": "path" + }, + { + "required": true, + "schema": { + "type": "string", + "format": "uuid", + "title": "Job Id" + }, + "name": "job_id", + "in": "path" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobOutputs" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/studies/{study_id}/jobs/{job_id}/outputs/log-links": { + "get": { + "tags": [ + "studies" + ], + "summary": "Get download links for study job log files", + "operationId": "get_study_job_output_logfile", "parameters": [ { "required": true, @@ -3443,53 +4861,23 @@ "in": "path" }, { - "required": false, - "schema": { - "type": "boolean", - "title": "Hidden", - "default": true - }, - "name": "hidden", - "in": "query" - }, - { - "required": false, - "schema": { - "type": "string", - "format": "uuid", - "title": "X-Simcore-Parent-Project-Uuid" - }, - "name": "x-simcore-parent-project-uuid", - "in": "header" - }, - { - "required": false, + "required": true, "schema": { "type": "string", "format": "uuid", - "title": "X-Simcore-Parent-Node-Id" + "title": "Job Id" }, - "name": "x-simcore-parent-node-id", - "in": "header" + "name": "job_id", + "in": "path" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JobInputs" - } - } - }, - "required": true - }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Job" + "$ref": "#/components/schemas/JobLogsMap" } } } @@ -3512,14 +4900,14 @@ ] } }, - "/v0/studies/{study_id}/jobs/{job_id}": { - "delete": { + "/v0/studies/{study_id}/jobs/{job_id}/metadata": { + "get": { "tags": [ "studies" ], - "summary": "Delete Study Job", - "description": "Deletes an existing study job", - "operationId": "delete_study_job", + "summary": "Get Study Job Custom Metadata", + "description": "Get custom metadata from a study's job\n\nNew in *version 0.7*", + "operationId": "get_study_job_custom_metadata", "parameters": [ { "required": true, @@ -3543,15 +4931,12 @@ } ], "responses": { - "204": { - "description": "Successful Response" - }, - "404": { - "description": "Not Found", + "200": { + "description": "Successful Response", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorGet" + "$ref": "#/components/schemas/JobMetadata" } } } @@ -3572,16 +4957,14 @@ "HTTPBasic": [] } ] - } - }, - "/v0/studies/{study_id}/jobs/{job_id}:start": { - "post": { + }, + "put": { "tags": [ "studies" ], - "summary": "Start Study Job", - "description": "Changed in *version 0.6.0*: Now responds with a 202 when successfully starting a computation", - "operationId": "start_study_job", + "summary": "Replace Study Job Custom Metadata", + "description": "Changes custom metadata of a study's job\n\nNew in *version 0.7*", + "operationId": "replace_study_job_custom_metadata", "parameters": [ { "required": true, @@ -3602,61 +4985,68 @@ }, "name": "job_id", "in": "path" - }, - { - "required": false, - "schema": { - "type": "integer", - "minimum": 0, - "title": "Cluster Id" - }, - "name": "cluster_id", - "in": "query" } ], - "responses": { - "202": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JobStatus" - } + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JobMetadataUpdate" } } }, - "402": { - "description": "Payment required", + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorGet" + "$ref": "#/components/schemas/JobMetadata" } } } }, - "404": { - "description": "Job/wallet/pricing details not found", + "422": { + "description": "Validation Error", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorGet" + "$ref": "#/components/schemas/HTTPValidationError" } } } - }, - "429": { - "description": "Too many requests", + } + }, + "security": [ + { + "HTTPBasic": [] + } + ] + } + }, + "/v0/wallets/default": { + "get": { + "tags": [ + "wallets" + ], + "summary": "Get Default Wallet", + "description": "Get default wallet\n\nNew in *version 0.7*", + "operationId": "get_default_wallet", + "responses": { + "200": { + "description": "Successful Response", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ErrorGet" + "$ref": "#/components/schemas/WalletGetWithAvailableCredits" } } } }, - "500": { - "description": "Internal server error", + "404": { + "description": "Wallet not found", "content": { "application/json": { "schema": { @@ -3665,8 +5055,8 @@ } } }, - "502": { - "description": "Unexpected error when communicating with backend service", + "403": { + "description": "Access to wallet is not allowed", "content": { "application/json": { "schema": { @@ -3675,8 +5065,8 @@ } } }, - "503": { - "description": "Service unavailable", + "429": { + "description": "Too many requests", "content": { "application/json": { "schema": { @@ -3685,8 +5075,8 @@ } } }, - "504": { - "description": "Request to a backend service timed out.", + "500": { + "description": "Internal server error", "content": { "application/json": { "schema": { @@ -3695,18 +5085,18 @@ } } }, - "200": { - "description": "Job already started", + "502": { + "description": "Unexpected error when communicating with backend service", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/JobStatus" + "$ref": "#/components/schemas/ErrorGet" } } } }, - "406": { - "description": "Cluster not found", + "503": { + "description": "Service unavailable", "content": { "application/json": { "schema": { @@ -3715,8 +5105,8 @@ } } }, - "422": { - "description": "Configuration error", + "504": { + "description": "Request to a backend service timed out.", "content": { "application/json": { "schema": { @@ -3733,32 +5123,22 @@ ] } }, - "/v0/studies/{study_id}/jobs/{job_id}:stop": { - "post": { + "/v0/wallets/{wallet_id}": { + "get": { "tags": [ - "studies" + "wallets" ], - "summary": "Stop Study Job", - "operationId": "stop_study_job", + "summary": "Get Wallet", + "description": "Get wallet\n\nNew in *version 0.7*", + "operationId": "get_wallet", "parameters": [ { "required": true, "schema": { - "type": "string", - "format": "uuid", - "title": "Study Id" - }, - "name": "study_id", - "in": "path" - }, - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Job Id" + "type": "integer", + "title": "Wallet Id" }, - "name": "job_id", + "name": "wallet_id", "in": "path" } ], @@ -3768,181 +5148,77 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/JobStatus" + "$ref": "#/components/schemas/WalletGetWithAvailableCredits" } } } }, - "422": { - "description": "Validation Error", + "404": { + "description": "Wallet not found", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/ErrorGet" } } } - } - }, - "security": [ - { - "HTTPBasic": [] - } - ] - } - }, - "/v0/studies/{study_id}/jobs/{job_id}:inspect": { - "post": { - "tags": [ - "studies" - ], - "summary": "Inspect Study Job", - "operationId": "inspect_study_job", - "parameters": [ - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Study Id" - }, - "name": "study_id", - "in": "path" }, - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Job Id" - }, - "name": "job_id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Successful Response", + "403": { + "description": "Access to wallet is not allowed", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/JobStatus" + "$ref": "#/components/schemas/ErrorGet" } } } }, - "422": { - "description": "Validation Error", + "429": { + "description": "Too many requests", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/ErrorGet" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorGet" } } } - } - }, - "security": [ - { - "HTTPBasic": [] - } - ] - } - }, - "/v0/studies/{study_id}/jobs/{job_id}/outputs": { - "post": { - "tags": [ - "studies" - ], - "summary": "Get Study Job Outputs", - "operationId": "get_study_job_outputs", - "parameters": [ - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Study Id" - }, - "name": "study_id", - "in": "path" }, - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Job Id" - }, - "name": "job_id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Successful Response", + "502": { + "description": "Unexpected error when communicating with backend service", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/JobOutputs" + "$ref": "#/components/schemas/ErrorGet" } } } }, - "422": { - "description": "Validation Error", + "503": { + "description": "Service unavailable", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/HTTPValidationError" + "$ref": "#/components/schemas/ErrorGet" } } } - } - }, - "security": [ - { - "HTTPBasic": [] - } - ] - } - }, - "/v0/studies/{study_id}/jobs/{job_id}/outputs/log-links": { - "get": { - "tags": [ - "studies" - ], - "summary": "Get download links for study job log files", - "operationId": "get_study_job_output_logfile", - "parameters": [ - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Study Id" - }, - "name": "study_id", - "in": "path" }, - { - "required": true, - "schema": { - "type": "string", - "format": "uuid", - "title": "Job Id" - }, - "name": "job_id", - "in": "path" - } - ], - "responses": { - "200": { - "description": "Successful Response", + "504": { + "description": "Request to a backend service timed out.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/JobLogsMap" + "$ref": "#/components/schemas/ErrorGet" } } } @@ -4438,6 +5714,79 @@ ], "title": "JobLogsMap" }, + "JobMetadata": { + "properties": { + "job_id": { + "type": "string", + "format": "uuid", + "title": "Job Id", + "description": "Parent Job" + }, + "metadata": { + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "string" + } + ] + }, + "type": "object", + "title": "Metadata", + "description": "Custom key-value map" + }, + "url": { + "type": "string", + "maxLength": 2083, + "minLength": 1, + "format": "uri", + "title": "Url", + "description": "Link to get this resource (self)" + } + }, + "type": "object", + "required": [ + "job_id", + "metadata", + "url" + ], + "title": "JobMetadata" + }, + "JobMetadataUpdate": { + "properties": { + "metadata": { + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + }, + { + "type": "number" + }, + { + "type": "string" + } + ] + }, + "type": "object", + "title": "Metadata", + "description": "Custom key-value map" + } + }, + "type": "object", + "title": "JobMetadataUpdate" + }, "JobOutputs": { "properties": { "job_id": { @@ -4730,6 +6079,41 @@ ], "title": "Page[File]" }, + "Page_Job_": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/Job" + }, + "type": "array", + "title": "Items" + }, + "total": { + "type": "integer", + "minimum": 0, + "title": "Total" + }, + "limit": { + "type": "integer", + "minimum": 1, + "title": "Limit" + }, + "offset": { + "type": "integer", + "minimum": 0, + "title": "Offset" + }, + "links": { + "$ref": "#/components/schemas/Links" + } + }, + "type": "object", + "required": [ + "items", + "links" + ], + "title": "Page[Job]" + }, "Page_Study_": { "properties": { "items": { @@ -4765,6 +6149,49 @@ ], "title": "Page[Study]" }, + "PricingPlanClassification": { + "type": "string", + "enum": [ + "TIER" + ], + "title": "PricingPlanClassification", + "description": "An enumeration." + }, + "PricingUnitGet": { + "properties": { + "pricingUnitId": { + "type": "integer", + "exclusiveMinimum": true, + "title": "Pricingunitid", + "minimum": 0 + }, + "unitName": { + "type": "string", + "title": "Unitname" + }, + "unitExtraInfo": { + "type": "object", + "title": "Unitextrainfo" + }, + "currentCostPerUnit": { + "type": "number", + "title": "Currentcostperunit" + }, + "default": { + "type": "boolean", + "title": "Default" + } + }, + "type": "object", + "required": [ + "pricingUnitId", + "unitName", + "unitExtraInfo", + "currentCostPerUnit", + "default" + ], + "title": "PricingUnitGet" + }, "Profile": { "properties": { "first_name": { @@ -4867,6 +6294,54 @@ "title": "RunningState", "description": "State of execution of a project's computational workflow\n\nSEE StateType for task state" }, + "ServicePricingPlanGet": { + "properties": { + "pricingPlanId": { + "type": "integer", + "exclusiveMinimum": true, + "title": "Pricingplanid", + "minimum": 0 + }, + "displayName": { + "type": "string", + "title": "Displayname" + }, + "description": { + "type": "string", + "title": "Description" + }, + "classification": { + "$ref": "#/components/schemas/PricingPlanClassification" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "title": "Createdat" + }, + "pricingPlanKey": { + "type": "string", + "title": "Pricingplankey" + }, + "pricingUnits": { + "items": { + "$ref": "#/components/schemas/PricingUnitGet" + }, + "type": "array", + "title": "Pricingunits" + } + }, + "type": "object", + "required": [ + "pricingPlanId", + "displayName", + "description", + "classification", + "createdAt", + "pricingPlanKey", + "pricingUnits" + ], + "title": "ServicePricingPlanGet" + }, "Solver": { "properties": { "id": { @@ -5129,6 +6604,73 @@ "type" ], "title": "ValidationError" + }, + "WalletGetWithAvailableCredits": { + "properties": { + "walletId": { + "type": "integer", + "exclusiveMinimum": true, + "title": "Walletid", + "minimum": 0 + }, + "name": { + "type": "string", + "maxLength": 100, + "minLength": 1, + "title": "Name" + }, + "description": { + "type": "string", + "title": "Description" + }, + "owner": { + "type": "integer", + "exclusiveMinimum": true, + "title": "Owner", + "minimum": 0 + }, + "thumbnail": { + "type": "string", + "title": "Thumbnail" + }, + "status": { + "$ref": "#/components/schemas/WalletStatus" + }, + "created": { + "type": "string", + "format": "date-time", + "title": "Created" + }, + "modified": { + "type": "string", + "format": "date-time", + "title": "Modified" + }, + "availableCredits": { + "type": "number", + "title": "Availablecredits" + } + }, + "type": "object", + "required": [ + "walletId", + "name", + "owner", + "status", + "created", + "modified", + "availableCredits" + ], + "title": "WalletGetWithAvailableCredits" + }, + "WalletStatus": { + "type": "string", + "enum": [ + "ACTIVE", + "INACTIVE" + ], + "title": "WalletStatus", + "description": "An enumeration." } }, "securitySchemes": { diff --git a/services/api-server/setup.cfg b/services/api-server/setup.cfg index 5cef2727de76..da01c1bbd3ea 100644 --- a/services/api-server/setup.cfg +++ b/services/api-server/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.6.0 +current_version = 0.7.0 commit = True message = services/api-server version: {current_version} → {new_version} tag = False @@ -10,12 +10,12 @@ commit_args = --no-verify [tool:pytest] asyncio_mode = auto addopts = --strict-markers -markers = +markers = slow: marks tests as slow (deselect with '-m "not slow"') acceptance_test: "marks tests as 'acceptance tests' i.e. does the system do what the user expects? Typically those are workflows." testit: "marks test to run during development" [mypy] -plugins = +plugins = pydantic.mypy sqlalchemy.ext.mypy.plugin diff --git a/services/api-server/src/simcore_service_api_server/api/routes/files.py b/services/api-server/src/simcore_service_api_server/api/routes/files.py index a89771dc490c..76110352782d 100644 --- a/services/api-server/src/simcore_service_api_server/api/routes/files.py +++ b/services/api-server/src/simcore_service_api_server/api/routes/files.py @@ -2,7 +2,6 @@ import datetime import io import logging -from textwrap import dedent from typing import IO, Annotated, Any from uuid import UUID @@ -10,7 +9,6 @@ from fastapi import File as FileParam from fastapi import Header, Request, UploadFile, status from fastapi.exceptions import HTTPException -from fastapi.responses import HTMLResponse from fastapi_pagination.api import create_page from models_library.api_schemas_storage import ETag, FileUploadCompletionBody, LinkType from models_library.basic_types import SHA256Str @@ -29,7 +27,6 @@ from starlette.datastructures import URL from starlette.responses import RedirectResponse -from ..._meta import API_VTAG from ...exceptions.service_errors_utils import DEFAULT_BACKEND_SERVICE_STATUS_CODES from ...models.pagination import Page, PaginationParams from ...models.schemas.errors import ErrorGet @@ -158,7 +155,11 @@ def _get_spooled_file_size(file_io: IO) -> int: return file_size -@router.put("/content", response_model=File, responses=_FILE_STATUS_CODES) +@router.put( + "/content", + response_model=File, + responses=_FILE_STATUS_CODES, +) @cancel_on_disconnect async def upload_file( request: Request, @@ -433,24 +434,3 @@ async def download_file( _logger.info("Downloading %s to %s ...", file_meta, presigned_download_link) return RedirectResponse(presigned_download_link) - - -async def files_upload_multiple_view(): - """Extra **Web form** to upload multiple files at http://localhost:8000/v0/files/upload-form-view - and overcomes the limitations of Swagger-UI view - - NOTE: Only enabled if DEBUG=1 - NOTE: As of 2020-10-07, Swagger UI doesn't support multiple file uploads in the same form field - """ - return HTMLResponse( - content=dedent( - f""" -
- - - """ - ) - ) diff --git a/services/api-server/src/simcore_service_api_server/api/routes/solvers.py b/services/api-server/src/simcore_service_api_server/api/routes/solvers.py index 18e238208266..01e58dc2653d 100644 --- a/services/api-server/src/simcore_service_api_server/api/routes/solvers.py +++ b/services/api-server/src/simcore_service_api_server/api/routes/solvers.py @@ -265,7 +265,8 @@ async def list_solver_ports( @router.get( "/{solver_key:path}/releases/{version}/pricing_plan", response_model=ServicePricingPlanGet, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, + description="Gets solver pricing plan\n\n" + + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7"), responses=_SOLVER_STATUS_CODES, ) async def get_solver_pricing_plan( diff --git a/services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs.py b/services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs.py index 560d656d5d4e..0cdbfdf7e0a3 100644 --- a/services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs.py +++ b/services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs.py @@ -40,7 +40,6 @@ from ..dependencies.authentication import get_current_user_id, get_product_name from ..dependencies.services import get_api_client from ..dependencies.webserver import AuthSession, get_webserver_session -from ._common import API_SERVER_DEV_FEATURES_ENABLED from ._constants import FMSG_CHANGELOG_ADDED_IN_VERSION, FMSG_CHANGELOG_NEW_IN_VERSION _logger = logging.getLogger(__name__) @@ -145,9 +144,8 @@ async def create_job( "/{solver_key:path}/releases/{version}/jobs/{job_id:uuid}", status_code=status.HTTP_204_NO_CONTENT, responses=JOBS_STATUS_CODES, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, description="Deletes an existing solver job\n\n" - + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.5"), + + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7"), ) async def delete_job( solver_key: SolverKeyId, @@ -271,9 +269,8 @@ async def inspect_job( "/{solver_key:path}/releases/{version}/jobs/{job_id:uuid}/metadata", response_model=JobMetadata, responses=METADATA_STATUS_CODES, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, description="Updates custom metadata from a job\n\n" - + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.5"), + + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7"), ) async def replace_job_custom_metadata( solver_key: SolverKeyId, diff --git a/services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs_getters.py b/services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs_getters.py index 2be5ac934d11..fb98a858e475 100644 --- a/services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs_getters.py +++ b/services/api-server/src/simcore_service_api_server/api/routes/solvers_jobs_getters.py @@ -52,7 +52,6 @@ from ..dependencies.rabbitmq import get_log_check_timeout, get_log_distributor from ..dependencies.services import get_api_client from ..dependencies.webserver import AuthSession, get_webserver_session -from ._common import API_SERVER_DEV_FEATURES_ENABLED from ._constants import FMSG_CHANGELOG_NEW_IN_VERSION from .solvers_jobs import ( JOBS_STATUS_CODES, @@ -128,7 +127,8 @@ async def list_jobs( ): """List of jobs in a specific released solver (limited to 20 jobs) - SEE `get_jobs_page` for paginated version of this function + - DEPRECATION: This implementation and returned values are deprecated and the will be replaced by that of get_jobs_page + - SEE `get_jobs_page` for paginated version of this function """ solver = await catalog_client.get_service( @@ -158,7 +158,6 @@ async def list_jobs( "/{solver_key:path}/releases/{version}/jobs/page", response_model=Page[Job], responses=JOBS_STATUS_CODES, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, description=( "List of jobs on a specific released solver (includes pagination)\n\n" + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7") @@ -349,9 +348,8 @@ async def get_job_output_logfile( "/{solver_key:path}/releases/{version}/jobs/{job_id:uuid}/metadata", response_model=JobMetadata, responses=METADATA_STATUS_CODES, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, description="Gets custom metadata from a job\n\n" - + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.5"), + + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7"), ) async def get_job_custom_metadata( solver_key: SolverKeyId, @@ -380,7 +378,7 @@ async def get_job_custom_metadata( "/{solver_key:path}/releases/{version}/jobs/{job_id:uuid}/wallet", response_model=WalletGetWithAvailableCredits | None, responses=WALLET_STATUS_CODES, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, + description=("Get job wallet\n\n" + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7")), ) async def get_job_wallet( solver_key: SolverKeyId, @@ -400,7 +398,9 @@ async def get_job_wallet( "/{solver_key:path}/releases/{version}/jobs/{job_id:uuid}/pricing_unit", response_model=PricingUnitGet | None, responses=_PRICING_UNITS_STATUS_CODES, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, + description=( + "Get job pricing unit\n\n" + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7") + ), ) async def get_job_pricing_unit( solver_key: SolverKeyId, diff --git a/services/api-server/src/simcore_service_api_server/api/routes/studies_jobs.py b/services/api-server/src/simcore_service_api_server/api/routes/studies_jobs.py index 60916446809b..177b50d1e6cc 100644 --- a/services/api-server/src/simcore_service_api_server/api/routes/studies_jobs.py +++ b/services/api-server/src/simcore_service_api_server/api/routes/studies_jobs.py @@ -52,7 +52,7 @@ from ...services.webserver import AuthSession from ..dependencies.application import get_reverse_url_mapper from ._common import API_SERVER_DEV_FEATURES_ENABLED -from ._constants import FMSG_CHANGELOG_CHANGED_IN_VERSION +from ._constants import FMSG_CHANGELOG_CHANGED_IN_VERSION, FMSG_CHANGELOG_NEW_IN_VERSION _logger = logging.getLogger(__name__) router = APIRouter() @@ -333,7 +333,10 @@ async def get_study_job_output_logfile( @router.get( "/{study_id}/jobs/{job_id}/metadata", response_model=JobMetadata, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, + description=( + "Get custom metadata from a study's job\n\n" + + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7") + ), ) async def get_study_job_custom_metadata( study_id: StudyID, @@ -341,7 +344,6 @@ async def get_study_job_custom_metadata( webserver_api: Annotated[AuthSession, Depends(get_webserver_session)], url_for: Annotated[Callable, Depends(get_reverse_url_mapper)], ): - """Gets custom metadata from a job""" job_name = _compose_job_resource_name(study_id, job_id) msg = f"Gets metadata attached to study_id={study_id!r} job_id={job_id!r}.\njob_name={job_name!r}.\nSEE https://github.com/ITISFoundation/osparc-simcore/issues/4313" _logger.debug(msg) @@ -361,7 +363,10 @@ async def get_study_job_custom_metadata( @router.put( "/{study_id}/jobs/{job_id}/metadata", response_model=JobMetadata, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, + description=( + "Changes custom metadata of a study's job\n\n" + + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7") + ), ) async def replace_study_job_custom_metadata( study_id: StudyID, @@ -370,7 +375,6 @@ async def replace_study_job_custom_metadata( webserver_api: Annotated[AuthSession, Depends(get_webserver_session)], url_for: Annotated[Callable, Depends(get_reverse_url_mapper)], ): - """Changes job's custom metadata""" job_name = _compose_job_resource_name(study_id, job_id) msg = f"Attaches metadata={replace.metadata!r} to study_id={study_id!r} job_id={job_id!r}.\njob_name={job_name!r}.\nSEE https://github.com/ITISFoundation/osparc-simcore/issues/4313" diff --git a/services/api-server/src/simcore_service_api_server/api/routes/wallets.py b/services/api-server/src/simcore_service_api_server/api/routes/wallets.py index 0043dce61575..0b3df66b1d54 100644 --- a/services/api-server/src/simcore_service_api_server/api/routes/wallets.py +++ b/services/api-server/src/simcore_service_api_server/api/routes/wallets.py @@ -7,7 +7,7 @@ from ...exceptions.service_errors_utils import DEFAULT_BACKEND_SERVICE_STATUS_CODES from ...models.schemas.errors import ErrorGet from ..dependencies.webserver import AuthSession, get_webserver_session -from ._common import API_SERVER_DEV_FEATURES_ENABLED +from ._constants import FMSG_CHANGELOG_NEW_IN_VERSION _logger = logging.getLogger(__name__) @@ -28,8 +28,8 @@ @router.get( "/default", + description="Get default wallet\n\n" + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7"), response_model=WalletGetWithAvailableCredits, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, responses=WALLET_STATUS_CODES, ) async def get_default_wallet( @@ -41,8 +41,8 @@ async def get_default_wallet( @router.get( "/{wallet_id}", response_model=WalletGetWithAvailableCredits, - include_in_schema=API_SERVER_DEV_FEATURES_ENABLED, responses=WALLET_STATUS_CODES, + description="Get wallet\n\n" + FMSG_CHANGELOG_NEW_IN_VERSION.format("0.7"), ) async def get_wallet( wallet_id: int,