diff --git a/api/swagger.json b/api/swagger.json index c05ec77..310297f 100644 --- a/api/swagger.json +++ b/api/swagger.json @@ -201,7 +201,7 @@ "200": { "description": "Success message", "schema": { - "$ref": "#/definitions/api.DefaultJobApiResponse" + "$ref": "#/definitions/api.DefaultApiResponse" } }, "400": { @@ -271,7 +271,7 @@ "200": { "description": "Success message", "schema": { - "$ref": "#/definitions/api.DefaultJobApiResponse" + "$ref": "#/definitions/api.DefaultApiResponse" } }, "400": { @@ -341,7 +341,7 @@ "200": { "description": "Success message", "schema": { - "$ref": "#/definitions/api.DefaultJobApiResponse" + "$ref": "#/definitions/api.DefaultApiResponse" } }, "400": { @@ -460,7 +460,7 @@ "ApiKeyAuth": [] } ], - "description": "Job specified in request body will be saved to database as \"running\" with new DB ID.\nJob specifications follow the 'JobMeta' scheme, API will fail to execute if requirements are not met.", + "description": "Job specified in request body will be saved to database as \"running\" with new DB ID.\nJob specifications follow the 'Job' scheme, API will fail to execute if requirements are not met.", "consumes": [ "application/json" ], @@ -478,7 +478,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/schema.JobMeta" + "$ref": "#/definitions/schema.Job" } } ], @@ -486,7 +486,7 @@ "201": { "description": "Job added successfully", "schema": { - "$ref": "#/definitions/api.DefaultJobApiResponse" + "$ref": "#/definitions/api.DefaultApiResponse" } }, "400": { @@ -529,7 +529,7 @@ "ApiKeyAuth": [] } ], - "description": "Job to stop is specified by request body. All fields are required in this case.\nReturns full job resource information according to 'JobMeta' scheme.", + "description": "Job to stop is specified by request body. All fields are required in this case.\nReturns full job resource information according to 'Job' scheme.", "produces": [ "application/json" ], @@ -552,7 +552,7 @@ "200": { "description": "Success message", "schema": { - "$ref": "#/definitions/schema.JobMeta" + "$ref": "#/definitions/schema.Job" } }, "400": { @@ -674,7 +674,7 @@ "ApiKeyAuth": [] } ], - "description": "Job to get is specified by database ID\nReturns full job resource information according to 'JobMeta' scheme and all metrics according to 'JobData'.", + "description": "Job to get is specified by database ID\nReturns full job resource information according to 'Job' scheme and all metrics according to 'JobData'.", "produces": [ "application/json" ], @@ -748,7 +748,7 @@ "ApiKeyAuth": [] } ], - "description": "Job to get is specified by database ID\nReturns full job resource information according to 'JobMeta' scheme and all metrics according to 'JobData'.", + "description": "Job to get is specified by database ID\nReturns full job resource information according to 'Job' scheme and all metrics according to 'JobData'.", "consumes": [ "application/json" ], @@ -826,6 +826,66 @@ } } }, + "/api/nodestats/": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Returns a JSON-encoded list of users.\nRequired query-parameter defines if all users or only users with additional special roles are returned.", + "produces": [ + "application/json" + ], + "tags": [ + "Nodestates" + ], + "summary": "Deliver updated Slurm node states", + "parameters": [ + { + "description": "Request body containing nodes and their states", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.UpdateNodeStatesRequest" + } + } + ], + "responses": { + "200": { + "description": "Success message", + "schema": { + "$ref": "#/definitions/api.DefaultApiResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.ErrorResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/api.ErrorResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/api.ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.ErrorResponse" + } + } + } + } + }, "/api/users/": { "get": { "security": [ @@ -1074,7 +1134,7 @@ } } }, - "api.DefaultJobApiResponse": { + "api.DefaultApiResponse": { "type": "object", "properties": { "msg": { @@ -1168,7 +1228,7 @@ "description": "Array of jobs", "type": "array", "items": { - "$ref": "#/definitions/schema.JobMeta" + "$ref": "#/definitions/schema.Job" } }, "page": { @@ -1191,6 +1251,20 @@ } } }, + "api.Node": { + "type": "object", + "properties": { + "hostname": { + "type": "string" + }, + "states": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "api.StopJobApiRequest": { "type": "object", "required": [ @@ -1224,6 +1298,21 @@ } } }, + "api.UpdateNodeStatesRequest": { + "type": "object", + "properties": { + "cluster": { + "type": "string", + "example": "fritz" + }, + "nodes": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Node" + } + } + } + }, "schema.Accelerator": { "type": "object", "properties": { @@ -1259,7 +1348,6 @@ } }, "schema.Job": { - "description": "Information of a HPC job.", "type": "object", "properties": { "arrayJobId": { @@ -1357,6 +1445,12 @@ "type": "string", "example": "abcd200" }, + "requestedMemory": { + "description": "in MB", + "type": "integer", + "minimum": 1, + "example": 128000 + }, "resources": { "type": "array", "items": { @@ -1368,7 +1462,14 @@ "example": 4 }, "startTime": { - "type": "string" + "type": "integer", + "example": 1649723812 + }, + "statistics": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schema.JobStatistics" + } }, "subCluster": { "type": "string", @@ -1416,147 +1517,6 @@ } } }, - "schema.JobMeta": { - "description": "Meta data information of a HPC job.", - "type": "object", - "properties": { - "arrayJobId": { - "type": "integer", - "example": 123000 - }, - "cluster": { - "type": "string", - "example": "fritz" - }, - "concurrentJobs": { - "$ref": "#/definitions/schema.JobLinkResultList" - }, - "duration": { - "type": "integer", - "minimum": 1, - "example": 43200 - }, - "energy": { - "type": "number" - }, - "energyFootprint": { - "type": "object", - "additionalProperties": { - "type": "number" - } - }, - "exclusive": { - "type": "integer", - "maximum": 2, - "minimum": 0, - "example": 1 - }, - "footprint": { - "type": "object", - "additionalProperties": { - "type": "number" - } - }, - "id": { - "type": "integer" - }, - "jobId": { - "type": "integer", - "example": 123000 - }, - "jobState": { - "enum": [ - "completed", - "failed", - "cancelled", - "stopped", - "timeout", - "out_of_memory" - ], - "allOf": [ - { - "$ref": "#/definitions/schema.JobState" - } - ], - "example": "completed" - }, - "metaData": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "monitoringStatus": { - "type": "integer", - "maximum": 3, - "minimum": 0, - "example": 1 - }, - "numAcc": { - "type": "integer", - "minimum": 1, - "example": 2 - }, - "numHwthreads": { - "type": "integer", - "minimum": 1, - "example": 20 - }, - "numNodes": { - "type": "integer", - "minimum": 1, - "example": 2 - }, - "partition": { - "type": "string", - "example": "main" - }, - "project": { - "type": "string", - "example": "abcd200" - }, - "resources": { - "type": "array", - "items": { - "$ref": "#/definitions/schema.Resource" - } - }, - "smt": { - "type": "integer", - "example": 4 - }, - "startTime": { - "type": "integer", - "minimum": 1, - "example": 1649723812 - }, - "statistics": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/schema.JobStatistics" - } - }, - "subCluster": { - "type": "string", - "example": "main" - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/schema.Tag" - } - }, - "user": { - "type": "string", - "example": "abcd100h" - }, - "walltime": { - "type": "integer", - "minimum": 1, - "example": 86400 - } - } - }, "schema.JobMetric": { "type": "object", "properties": { @@ -1884,6 +1844,9 @@ }, "remove": { "type": "boolean" + }, + "unit": { + "$ref": "#/definitions/schema.Unit" } } }, diff --git a/api/swagger.yaml b/api/swagger.yaml index 26210be..1c57f2d 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -31,7 +31,7 @@ definitions: example: Debug type: string type: object - api.DefaultJobApiResponse: + api.DefaultApiResponse: properties: msg: type: string @@ -96,7 +96,7 @@ definitions: jobs: description: Array of jobs items: - $ref: '#/definitions/schema.JobMeta' + $ref: '#/definitions/schema.Job' type: array page: description: Page id returned @@ -111,6 +111,15 @@ definitions: scope: $ref: '#/definitions/schema.MetricScope' type: object + api.Node: + properties: + hostname: + type: string + states: + items: + type: string + type: array + type: object api.StopJobApiRequest: properties: cluster: @@ -133,6 +142,16 @@ definitions: - jobState - stopTime type: object + api.UpdateNodeStatesRequest: + properties: + cluster: + example: fritz + type: string + nodes: + items: + $ref: '#/definitions/api.Node' + type: array + type: object schema.Accelerator: properties: id: @@ -156,7 +175,6 @@ definitions: type: array type: object schema.Job: - description: Information of a HPC job. properties: arrayJobId: example: 123000 @@ -228,6 +246,11 @@ definitions: project: example: abcd200 type: string + requestedMemory: + description: in MB + example: 128000 + minimum: 1 + type: integer resources: items: $ref: '#/definitions/schema.Resource' @@ -236,7 +259,12 @@ definitions: example: 4 type: integer startTime: - type: string + example: 1649723812 + type: integer + statistics: + additionalProperties: + $ref: '#/definitions/schema.JobStatistics' + type: object subCluster: example: main type: string @@ -268,109 +296,6 @@ definitions: $ref: '#/definitions/schema.JobLink' type: array type: object - schema.JobMeta: - description: Meta data information of a HPC job. - properties: - arrayJobId: - example: 123000 - type: integer - cluster: - example: fritz - type: string - concurrentJobs: - $ref: '#/definitions/schema.JobLinkResultList' - duration: - example: 43200 - minimum: 1 - type: integer - energy: - type: number - energyFootprint: - additionalProperties: - type: number - type: object - exclusive: - example: 1 - maximum: 2 - minimum: 0 - type: integer - footprint: - additionalProperties: - type: number - type: object - id: - type: integer - jobId: - example: 123000 - type: integer - jobState: - allOf: - - $ref: '#/definitions/schema.JobState' - enum: - - completed - - failed - - cancelled - - stopped - - timeout - - out_of_memory - example: completed - metaData: - additionalProperties: - type: string - type: object - monitoringStatus: - example: 1 - maximum: 3 - minimum: 0 - type: integer - numAcc: - example: 2 - minimum: 1 - type: integer - numHwthreads: - example: 20 - minimum: 1 - type: integer - numNodes: - example: 2 - minimum: 1 - type: integer - partition: - example: main - type: string - project: - example: abcd200 - type: string - resources: - items: - $ref: '#/definitions/schema.Resource' - type: array - smt: - example: 4 - type: integer - startTime: - example: 1649723812 - minimum: 1 - type: integer - statistics: - additionalProperties: - $ref: '#/definitions/schema.JobStatistics' - type: object - subCluster: - example: main - type: string - tags: - items: - $ref: '#/definitions/schema.Tag' - type: array - user: - example: abcd100h - type: string - walltime: - example: 86400 - minimum: 1 - type: integer - type: object schema.JobMetric: properties: series: @@ -599,6 +524,8 @@ definitions: type: number remove: type: boolean + unit: + $ref: '#/definitions/schema.Unit' type: object schema.Tag: description: Defines a tag using name and type. @@ -776,7 +703,7 @@ paths: get: description: |- Job to get is specified by database ID - Returns full job resource information according to 'JobMeta' scheme and all metrics according to 'JobData'. + Returns full job resource information according to 'Job' scheme and all metrics according to 'JobData'. parameters: - description: Database ID of Job in: path @@ -829,7 +756,7 @@ paths: - application/json description: |- Job to get is specified by database ID - Returns full job resource information according to 'JobMeta' scheme and all metrics according to 'JobData'. + Returns full job resource information according to 'Job' scheme and all metrics according to 'JobData'. parameters: - description: Database ID of Job in: path @@ -900,7 +827,7 @@ paths: "200": description: Success message schema: - $ref: '#/definitions/api.DefaultJobApiResponse' + $ref: '#/definitions/api.DefaultApiResponse' "400": description: Bad Request schema: @@ -947,7 +874,7 @@ paths: "200": description: Success message schema: - $ref: '#/definitions/api.DefaultJobApiResponse' + $ref: '#/definitions/api.DefaultApiResponse' "400": description: Bad Request schema: @@ -994,7 +921,7 @@ paths: "200": description: Success message schema: - $ref: '#/definitions/api.DefaultJobApiResponse' + $ref: '#/definitions/api.DefaultApiResponse' "400": description: Bad Request schema: @@ -1078,21 +1005,21 @@ paths: - application/json description: |- Job specified in request body will be saved to database as "running" with new DB ID. - Job specifications follow the 'JobMeta' scheme, API will fail to execute if requirements are not met. + Job specifications follow the 'Job' scheme, API will fail to execute if requirements are not met. parameters: - description: Job to add in: body name: request required: true schema: - $ref: '#/definitions/schema.JobMeta' + $ref: '#/definitions/schema.Job' produces: - application/json responses: "201": description: Job added successfully schema: - $ref: '#/definitions/api.DefaultJobApiResponse' + $ref: '#/definitions/api.DefaultApiResponse' "400": description: Bad Request schema: @@ -1123,7 +1050,7 @@ paths: post: description: |- Job to stop is specified by request body. All fields are required in this case. - Returns full job resource information according to 'JobMeta' scheme. + Returns full job resource information according to 'Job' scheme. parameters: - description: All fields required in: body @@ -1137,7 +1064,7 @@ paths: "200": description: Success message schema: - $ref: '#/definitions/schema.JobMeta' + $ref: '#/definitions/schema.Job' "400": description: Bad Request schema: @@ -1217,6 +1144,46 @@ paths: summary: Adds one or more tags to a job tags: - Job add and modify + /api/nodestats/: + post: + description: |- + Returns a JSON-encoded list of users. + Required query-parameter defines if all users or only users with additional special roles are returned. + parameters: + - description: Request body containing nodes and their states + in: body + name: request + required: true + schema: + $ref: '#/definitions/api.UpdateNodeStatesRequest' + produces: + - application/json + responses: + "200": + description: Success message + schema: + $ref: '#/definitions/api.DefaultApiResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/api.ErrorResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/api.ErrorResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/api.ErrorResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/api.ErrorResponse' + security: + - ApiKeyAuth: [] + summary: Deliver updated Slurm node states + tags: + - Nodestates /api/users/: get: description: |- diff --git a/internal/api/docs.go b/internal/api/docs.go index c1cd391..d7b8464 100644 --- a/internal/api/docs.go +++ b/internal/api/docs.go @@ -208,7 +208,7 @@ const docTemplate = `{ "200": { "description": "Success message", "schema": { - "$ref": "#/definitions/api.DefaultJobApiResponse" + "$ref": "#/definitions/api.DefaultApiResponse" } }, "400": { @@ -278,7 +278,7 @@ const docTemplate = `{ "200": { "description": "Success message", "schema": { - "$ref": "#/definitions/api.DefaultJobApiResponse" + "$ref": "#/definitions/api.DefaultApiResponse" } }, "400": { @@ -348,7 +348,7 @@ const docTemplate = `{ "200": { "description": "Success message", "schema": { - "$ref": "#/definitions/api.DefaultJobApiResponse" + "$ref": "#/definitions/api.DefaultApiResponse" } }, "400": { @@ -467,7 +467,7 @@ const docTemplate = `{ "ApiKeyAuth": [] } ], - "description": "Job specified in request body will be saved to database as \"running\" with new DB ID.\nJob specifications follow the 'JobMeta' scheme, API will fail to execute if requirements are not met.", + "description": "Job specified in request body will be saved to database as \"running\" with new DB ID.\nJob specifications follow the 'Job' scheme, API will fail to execute if requirements are not met.", "consumes": [ "application/json" ], @@ -485,7 +485,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/schema.JobMeta" + "$ref": "#/definitions/schema.Job" } } ], @@ -493,7 +493,7 @@ const docTemplate = `{ "201": { "description": "Job added successfully", "schema": { - "$ref": "#/definitions/api.DefaultJobApiResponse" + "$ref": "#/definitions/api.DefaultApiResponse" } }, "400": { @@ -536,7 +536,7 @@ const docTemplate = `{ "ApiKeyAuth": [] } ], - "description": "Job to stop is specified by request body. All fields are required in this case.\nReturns full job resource information according to 'JobMeta' scheme.", + "description": "Job to stop is specified by request body. All fields are required in this case.\nReturns full job resource information according to 'Job' scheme.", "produces": [ "application/json" ], @@ -559,7 +559,7 @@ const docTemplate = `{ "200": { "description": "Success message", "schema": { - "$ref": "#/definitions/schema.JobMeta" + "$ref": "#/definitions/schema.Job" } }, "400": { @@ -681,7 +681,7 @@ const docTemplate = `{ "ApiKeyAuth": [] } ], - "description": "Job to get is specified by database ID\nReturns full job resource information according to 'JobMeta' scheme and all metrics according to 'JobData'.", + "description": "Job to get is specified by database ID\nReturns full job resource information according to 'Job' scheme and all metrics according to 'JobData'.", "produces": [ "application/json" ], @@ -755,7 +755,7 @@ const docTemplate = `{ "ApiKeyAuth": [] } ], - "description": "Job to get is specified by database ID\nReturns full job resource information according to 'JobMeta' scheme and all metrics according to 'JobData'.", + "description": "Job to get is specified by database ID\nReturns full job resource information according to 'Job' scheme and all metrics according to 'JobData'.", "consumes": [ "application/json" ], @@ -833,6 +833,66 @@ const docTemplate = `{ } } }, + "/api/nodestats/": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Returns a JSON-encoded list of users.\nRequired query-parameter defines if all users or only users with additional special roles are returned.", + "produces": [ + "application/json" + ], + "tags": [ + "Nodestates" + ], + "summary": "Deliver updated Slurm node states", + "parameters": [ + { + "description": "Request body containing nodes and their states", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.UpdateNodeStatesRequest" + } + } + ], + "responses": { + "200": { + "description": "Success message", + "schema": { + "$ref": "#/definitions/api.DefaultApiResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/api.ErrorResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/api.ErrorResponse" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/api.ErrorResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/api.ErrorResponse" + } + } + } + } + }, "/api/users/": { "get": { "security": [ @@ -1081,7 +1141,7 @@ const docTemplate = `{ } } }, - "api.DefaultJobApiResponse": { + "api.DefaultApiResponse": { "type": "object", "properties": { "msg": { @@ -1175,7 +1235,7 @@ const docTemplate = `{ "description": "Array of jobs", "type": "array", "items": { - "$ref": "#/definitions/schema.JobMeta" + "$ref": "#/definitions/schema.Job" } }, "page": { @@ -1198,6 +1258,20 @@ const docTemplate = `{ } } }, + "api.Node": { + "type": "object", + "properties": { + "hostname": { + "type": "string" + }, + "states": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "api.StopJobApiRequest": { "type": "object", "required": [ @@ -1231,6 +1305,21 @@ const docTemplate = `{ } } }, + "api.UpdateNodeStatesRequest": { + "type": "object", + "properties": { + "cluster": { + "type": "string", + "example": "fritz" + }, + "nodes": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Node" + } + } + } + }, "schema.Accelerator": { "type": "object", "properties": { @@ -1266,7 +1355,6 @@ const docTemplate = `{ } }, "schema.Job": { - "description": "Information of a HPC job.", "type": "object", "properties": { "arrayJobId": { @@ -1364,6 +1452,12 @@ const docTemplate = `{ "type": "string", "example": "abcd200" }, + "requestedMemory": { + "description": "in MB", + "type": "integer", + "minimum": 1, + "example": 128000 + }, "resources": { "type": "array", "items": { @@ -1375,7 +1469,14 @@ const docTemplate = `{ "example": 4 }, "startTime": { - "type": "string" + "type": "integer", + "example": 1649723812 + }, + "statistics": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/schema.JobStatistics" + } }, "subCluster": { "type": "string", @@ -1423,147 +1524,6 @@ const docTemplate = `{ } } }, - "schema.JobMeta": { - "description": "Meta data information of a HPC job.", - "type": "object", - "properties": { - "arrayJobId": { - "type": "integer", - "example": 123000 - }, - "cluster": { - "type": "string", - "example": "fritz" - }, - "concurrentJobs": { - "$ref": "#/definitions/schema.JobLinkResultList" - }, - "duration": { - "type": "integer", - "minimum": 1, - "example": 43200 - }, - "energy": { - "type": "number" - }, - "energyFootprint": { - "type": "object", - "additionalProperties": { - "type": "number" - } - }, - "exclusive": { - "type": "integer", - "maximum": 2, - "minimum": 0, - "example": 1 - }, - "footprint": { - "type": "object", - "additionalProperties": { - "type": "number" - } - }, - "id": { - "type": "integer" - }, - "jobId": { - "type": "integer", - "example": 123000 - }, - "jobState": { - "enum": [ - "completed", - "failed", - "cancelled", - "stopped", - "timeout", - "out_of_memory" - ], - "allOf": [ - { - "$ref": "#/definitions/schema.JobState" - } - ], - "example": "completed" - }, - "metaData": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "monitoringStatus": { - "type": "integer", - "maximum": 3, - "minimum": 0, - "example": 1 - }, - "numAcc": { - "type": "integer", - "minimum": 1, - "example": 2 - }, - "numHwthreads": { - "type": "integer", - "minimum": 1, - "example": 20 - }, - "numNodes": { - "type": "integer", - "minimum": 1, - "example": 2 - }, - "partition": { - "type": "string", - "example": "main" - }, - "project": { - "type": "string", - "example": "abcd200" - }, - "resources": { - "type": "array", - "items": { - "$ref": "#/definitions/schema.Resource" - } - }, - "smt": { - "type": "integer", - "example": 4 - }, - "startTime": { - "type": "integer", - "minimum": 1, - "example": 1649723812 - }, - "statistics": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/schema.JobStatistics" - } - }, - "subCluster": { - "type": "string", - "example": "main" - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/schema.Tag" - } - }, - "user": { - "type": "string", - "example": "abcd100h" - }, - "walltime": { - "type": "integer", - "minimum": 1, - "example": 86400 - } - } - }, "schema.JobMetric": { "type": "object", "properties": { @@ -1891,6 +1851,9 @@ const docTemplate = `{ }, "remove": { "type": "boolean" + }, + "unit": { + "$ref": "#/definitions/schema.Unit" } } }, diff --git a/internal/api/job.go b/internal/api/job.go index 1af6c38..cce47c5 100644 --- a/internal/api/job.go +++ b/internal/api/job.go @@ -28,11 +28,6 @@ import ( "github.com/gorilla/mux" ) -// DefaultApiResponse model -type DefaultJobApiResponse struct { - Message string `json:"msg"` -} - // StopJobApiRequest model type StopJobApiRequest struct { JobId *int64 `json:"jobId" example:"123000"` @@ -224,7 +219,7 @@ func (api *RestApi) getJobs(rw http.ResponseWriter, r *http.Request) { // @summary Get job meta and optional all metric data // @tags Job query // @description Job to get is specified by database ID -// @description Returns full job resource information according to 'JobMeta' scheme and all metrics according to 'JobData'. +// @description Returns full job resource information according to 'Job' scheme and all metrics according to 'JobData'. // @produce json // @param id path int true "Database ID of Job" // @param all-metrics query bool false "Include all available metrics" @@ -316,7 +311,7 @@ func (api *RestApi) getCompleteJobById(rw http.ResponseWriter, r *http.Request) // @summary Get job meta and configurable metric data // @tags Job query // @description Job to get is specified by database ID -// @description Returns full job resource information according to 'JobMeta' scheme and all metrics according to 'JobData'. +// @description Returns full job resource information according to 'Job' scheme and all metrics according to 'JobData'. // @accept json // @produce json // @param id path int true "Database ID of Job" @@ -637,11 +632,11 @@ func (api *RestApi) removeTags(rw http.ResponseWriter, r *http.Request) { // @summary Adds a new job as "running" // @tags Job add and modify // @description Job specified in request body will be saved to database as "running" with new DB ID. -// @description Job specifications follow the 'JobMeta' scheme, API will fail to execute if requirements are not met. +// @description Job specifications follow the 'Job' scheme, API will fail to execute if requirements are not met. // @accept json // @produce json -// @param request body schema.JobMeta true "Job to add" -// @success 201 {object} api.DefaultJobApiResponse "Job added successfully" +// @param request body schema.Job true "Job to add" +// @success 201 {object} api.DefaultApiResponse "Job added successfully" // @failure 400 {object} api.ErrorResponse "Bad Request" // @failure 401 {object} api.ErrorResponse "Unauthorized" // @failure 403 {object} api.ErrorResponse "Forbidden" @@ -705,7 +700,7 @@ func (api *RestApi) startJob(rw http.ResponseWriter, r *http.Request) { log.Printf("new job (id: %d): cluster=%s, jobId=%d, user=%s, startTime=%d", id, req.Cluster, req.JobID, req.User, req.StartTime) rw.Header().Add("Content-Type", "application/json") rw.WriteHeader(http.StatusCreated) - json.NewEncoder(rw).Encode(DefaultJobApiResponse{ + json.NewEncoder(rw).Encode(DefaultApiResponse{ Message: "success", }) } @@ -714,10 +709,10 @@ func (api *RestApi) startJob(rw http.ResponseWriter, r *http.Request) { // @summary Marks job as completed and triggers archiving // @tags Job add and modify // @description Job to stop is specified by request body. All fields are required in this case. -// @description Returns full job resource information according to 'JobMeta' scheme. +// @description Returns full job resource information according to 'Job' scheme. // @produce json // @param request body api.StopJobApiRequest true "All fields required" -// @success 200 {object} schema.JobMeta "Success message" +// @success 200 {object} schema.Job "Success message" // @failure 400 {object} api.ErrorResponse "Bad Request" // @failure 401 {object} api.ErrorResponse "Unauthorized" // @failure 403 {object} api.ErrorResponse "Forbidden" @@ -762,7 +757,7 @@ func (api *RestApi) stopJobByRequest(rw http.ResponseWriter, r *http.Request) { // @description Job to remove is specified by database ID. This will not remove the job from the job archive. // @produce json // @param id path int true "Database ID of Job" -// @success 200 {object} api.DefaultJobApiResponse "Success message" +// @success 200 {object} api.DefaultApiResponse "Success message" // @failure 400 {object} api.ErrorResponse "Bad Request" // @failure 401 {object} api.ErrorResponse "Unauthorized" // @failure 403 {object} api.ErrorResponse "Forbidden" @@ -793,7 +788,7 @@ func (api *RestApi) deleteJobById(rw http.ResponseWriter, r *http.Request) { } rw.Header().Add("Content-Type", "application/json") rw.WriteHeader(http.StatusOK) - json.NewEncoder(rw).Encode(DefaultJobApiResponse{ + json.NewEncoder(rw).Encode(DefaultApiResponse{ Message: fmt.Sprintf("Successfully deleted job %s", id), }) } @@ -805,7 +800,7 @@ func (api *RestApi) deleteJobById(rw http.ResponseWriter, r *http.Request) { // @accept json // @produce json // @param request body api.DeleteJobApiRequest true "All fields required" -// @success 200 {object} api.DefaultJobApiResponse "Success message" +// @success 200 {object} api.DefaultApiResponse "Success message" // @failure 400 {object} api.ErrorResponse "Bad Request" // @failure 401 {object} api.ErrorResponse "Unauthorized" // @failure 403 {object} api.ErrorResponse "Forbidden" @@ -844,7 +839,7 @@ func (api *RestApi) deleteJobByRequest(rw http.ResponseWriter, r *http.Request) rw.Header().Add("Content-Type", "application/json") rw.WriteHeader(http.StatusOK) - json.NewEncoder(rw).Encode(DefaultJobApiResponse{ + json.NewEncoder(rw).Encode(DefaultApiResponse{ Message: fmt.Sprintf("Successfully deleted job %d", job.ID), }) } @@ -855,7 +850,7 @@ func (api *RestApi) deleteJobByRequest(rw http.ResponseWriter, r *http.Request) // @description Remove all jobs with start time before timestamp. The jobs will not be removed from the job archive. // @produce json // @param ts path int true "Unix epoch timestamp" -// @success 200 {object} api.DefaultJobApiResponse "Success message" +// @success 200 {object} api.DefaultApiResponse "Success message" // @failure 400 {object} api.ErrorResponse "Bad Request" // @failure 401 {object} api.ErrorResponse "Unauthorized" // @failure 403 {object} api.ErrorResponse "Forbidden" @@ -888,7 +883,7 @@ func (api *RestApi) deleteJobBefore(rw http.ResponseWriter, r *http.Request) { rw.Header().Add("Content-Type", "application/json") rw.WriteHeader(http.StatusOK) - json.NewEncoder(rw).Encode(DefaultJobApiResponse{ + json.NewEncoder(rw).Encode(DefaultApiResponse{ Message: fmt.Sprintf("Successfully deleted %d jobs", cnt), }) } @@ -927,7 +922,7 @@ func (api *RestApi) checkAndHandleStopJob(rw http.ResponseWriter, job *schema.Jo log.Printf("archiving job... (dbid: %d): cluster=%s, jobId=%d, user=%s, startTime=%d, duration=%d, state=%s", job.ID, job.Cluster, job.JobID, job.User, job.StartTime, job.Duration, job.State) - // Send a response (with status OK). This means that erros that happen from here on forward + // Send a response (with status OK). This means that errors that happen from here on forward // can *NOT* be communicated to the client. If reading from a MetricDataRepository or // writing to the filesystem fails, the client will not know. rw.Header().Add("Content-Type", "application/json") diff --git a/internal/api/node.go b/internal/api/node.go index 36fb6cc..675e5f6 100644 --- a/internal/api/node.go +++ b/internal/api/node.go @@ -46,16 +46,16 @@ func determineState(states []string) schema.NodeState { // updateNodeStates godoc // @summary Deliver updated Slurm node states -// @tags node +// @tags Nodestates // @description Returns a JSON-encoded list of users. // @description Required query-parameter defines if all users or only users with additional special roles are returned. // @produce json // @param request body UpdateNodeStatesRequest true "Request body containing nodes and their states" -// @success 200 {array} api.SuccessResponse "Success" -// @failure 400 {string} string "Bad Request" -// @failure 401 {string} string "Unauthorized" -// @failure 403 {string} string "Forbidden" -// @failure 500 {string} string "Internal Server Error" +// @success 200 {object} api.DefaultApiResponse "Success message" +// @failure 400 {object} api.ErrorResponse "Bad Request" +// @failure 401 {object} api.ErrorResponse "Unauthorized" +// @failure 403 {object} api.ErrorResponse "Forbidden" +// @failure 500 {object} api.ErrorResponse "Internal Server Error" // @security ApiKeyAuth // @router /api/nodestats/ [post] func (api *RestApi) updateNodeStates(rw http.ResponseWriter, r *http.Request) { diff --git a/internal/api/rest.go b/internal/api/rest.go index 54472d8..e2fc119 100644 --- a/internal/api/rest.go +++ b/internal/api/rest.go @@ -124,6 +124,11 @@ type ErrorResponse struct { Error string `json:"error"` // Error Message } +// DefaultApiResponse model +type DefaultApiResponse struct { + Message string `json:"msg"` +} + func handleError(err error, statusCode int, rw http.ResponseWriter) { log.Warnf("REST ERROR : %s", err.Error()) rw.Header().Add("Content-Type", "application/json") diff --git a/pkg/schema/job.go b/pkg/schema/job.go index 00051f4..9ef51aa 100644 --- a/pkg/schema/job.go +++ b/pkg/schema/job.go @@ -12,10 +12,11 @@ import ( // Job struct type // -// This type is used as the GraphQL interface and using sqlx as a table row. +// This type contains all metadata of a HPC job. // // Job model // @Description Information of a HPC job. + type Job struct { Cluster string `json:"cluster" db:"cluster" example:"fritz"` SubCluster string `json:"subCluster" db:"subcluster" example:"main"` @@ -50,25 +51,6 @@ type Job struct { StartTime int64 `json:"startTime" db:"start_time" example:"1649723812"` } -// JobMeta struct type -// -// When reading from the database or sending data via GraphQL, the start time -// can be in the much more convenient time.Time type. In the `meta.json` -// files, the start time is encoded as a unix epoch timestamp. This is why -// there is this struct, which contains all fields from the regular job -// struct, but "overwrites" the StartTime field with one of type int64. ID -// *int64 `json:"id,omitempty"` >> never used in the job-archive, only -// available via REST-API -// -// JobMeta model -// @Description Meta data information of a HPC job. -// type JobMeta struct { -// ID *int64 `json:"id,omitempty"` -// BaseJob -// Statistics map[string]JobStatistics `json:"statistics"` -// StartTime int64 `json:"startTime" db:"start_time" example:"1649723812" minimum:"1"` -// } - type JobLink struct { ID int64 `json:"id"` JobID int64 `json:"jobId"` diff --git a/pkg/schema/validate_test.go b/pkg/schema/validate_test.go index f4943f0..9d97dbf 100644 --- a/pkg/schema/validate_test.go +++ b/pkg/schema/validate_test.go @@ -35,9 +35,6 @@ func TestValidateConfig(t *testing.T) { } } -func TestValidateJobMeta(t *testing.T) { -} - func TestValidateCluster(t *testing.T) { json := []byte(`{ "name": "emmy",