mirror of
				https://github.com/ClusterCockpit/cc-backend
				synced 2025-10-30 23:45:06 +01:00 
			
		
		
		
	feat: add editMetaByRequest, specifies job by parameters instead of dbid
This commit is contained in:
		| @@ -383,8 +383,71 @@ | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "/api/jobs/edit_meta/": { | ||||
|             "patch": { | ||||
|                 "security": [ | ||||
|                     { | ||||
|                         "ApiKeyAuth": [] | ||||
|                     } | ||||
|                 ], | ||||
|                 "description": "Edit key value pairs in metadata json of job specified by jobID, StartTime and Cluster\nIf a key already exists its content will be overwritten", | ||||
|                 "consumes": [ | ||||
|                     "application/json" | ||||
|                 ], | ||||
|                 "produces": [ | ||||
|                     "application/json" | ||||
|                 ], | ||||
|                 "tags": [ | ||||
|                     "Job add and modify" | ||||
|                 ], | ||||
|                 "summary": "Edit meta-data json by request", | ||||
|                 "parameters": [ | ||||
|                     { | ||||
|                         "description": "Specifies job and payload to add or update", | ||||
|                         "name": "request", | ||||
|                         "in": "body", | ||||
|                         "required": true, | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.JobMetaRequest" | ||||
|                         } | ||||
|                     } | ||||
|                 ], | ||||
|                 "responses": { | ||||
|                     "200": { | ||||
|                         "description": "Updated job resource", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/schema.Job" | ||||
|                         } | ||||
|                     }, | ||||
|                     "400": { | ||||
|                         "description": "Bad Request", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.ErrorResponse" | ||||
|                         } | ||||
|                     }, | ||||
|                     "401": { | ||||
|                         "description": "Unauthorized", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.ErrorResponse" | ||||
|                         } | ||||
|                     }, | ||||
|                     "404": { | ||||
|                         "description": "Job does not exist", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.ErrorResponse" | ||||
|                         } | ||||
|                     }, | ||||
|                     "500": { | ||||
|                         "description": "Internal Server Error", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.ErrorResponse" | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "/api/jobs/edit_meta/{id}": { | ||||
|             "post": { | ||||
|             "patch": { | ||||
|                 "security": [ | ||||
|                     { | ||||
|                         "ApiKeyAuth": [] | ||||
| @@ -1177,6 +1240,37 @@ | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "api.JobMetaRequest": { | ||||
|             "type": "object", | ||||
|             "required": [ | ||||
|                 "jobId" | ||||
|             ], | ||||
|             "properties": { | ||||
|                 "cluster": { | ||||
|                     "description": "Cluster of job", | ||||
|                     "type": "string", | ||||
|                     "example": "fritz" | ||||
|                 }, | ||||
|                 "jobId": { | ||||
|                     "description": "Cluster Job ID of job", | ||||
|                     "type": "integer", | ||||
|                     "example": 123000 | ||||
|                 }, | ||||
|                 "payload": { | ||||
|                     "description": "Content to Add to Job Meta_Data", | ||||
|                     "allOf": [ | ||||
|                         { | ||||
|                             "$ref": "#/definitions/api.EditMetaRequest" | ||||
|                         } | ||||
|                     ] | ||||
|                 }, | ||||
|                 "startTime": { | ||||
|                     "description": "Start Time of job as epoch", | ||||
|                     "type": "integer", | ||||
|                     "example": 1649723812 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "api.JobMetricWithName": { | ||||
|             "type": "object", | ||||
|             "properties": { | ||||
|   | ||||
| @@ -102,6 +102,27 @@ definitions: | ||||
|         description: Page id returned | ||||
|         type: integer | ||||
|     type: object | ||||
|   api.JobMetaRequest: | ||||
|     properties: | ||||
|       cluster: | ||||
|         description: Cluster of job | ||||
|         example: fritz | ||||
|         type: string | ||||
|       jobId: | ||||
|         description: Cluster Job ID of job | ||||
|         example: 123000 | ||||
|         type: integer | ||||
|       payload: | ||||
|         allOf: | ||||
|         - $ref: '#/definitions/api.EditMetaRequest' | ||||
|         description: Content to Add to Job Meta_Data | ||||
|       startTime: | ||||
|         description: Start Time of job as epoch | ||||
|         example: 1649723812 | ||||
|         type: integer | ||||
|     required: | ||||
|     - jobId | ||||
|     type: object | ||||
|   api.JobMetricWithName: | ||||
|     properties: | ||||
|       metric: | ||||
| @@ -1025,8 +1046,50 @@ paths: | ||||
|       summary: Remove a job from the sql database | ||||
|       tags: | ||||
|       - Job remove | ||||
|   /api/jobs/edit_meta/: | ||||
|     patch: | ||||
|       consumes: | ||||
|       - application/json | ||||
|       description: |- | ||||
|         Edit key value pairs in metadata json of job specified by jobID, StartTime and Cluster | ||||
|         If a key already exists its content will be overwritten | ||||
|       parameters: | ||||
|       - description: Specifies job and payload to add or update | ||||
|         in: body | ||||
|         name: request | ||||
|         required: true | ||||
|         schema: | ||||
|           $ref: '#/definitions/api.JobMetaRequest' | ||||
|       produces: | ||||
|       - application/json | ||||
|       responses: | ||||
|         "200": | ||||
|           description: Updated job resource | ||||
|           schema: | ||||
|             $ref: '#/definitions/schema.Job' | ||||
|         "400": | ||||
|           description: Bad Request | ||||
|           schema: | ||||
|             $ref: '#/definitions/api.ErrorResponse' | ||||
|         "401": | ||||
|           description: Unauthorized | ||||
|           schema: | ||||
|             $ref: '#/definitions/api.ErrorResponse' | ||||
|         "404": | ||||
|           description: Job does not exist | ||||
|           schema: | ||||
|             $ref: '#/definitions/api.ErrorResponse' | ||||
|         "500": | ||||
|           description: Internal Server Error | ||||
|           schema: | ||||
|             $ref: '#/definitions/api.ErrorResponse' | ||||
|       security: | ||||
|       - ApiKeyAuth: [] | ||||
|       summary: Edit meta-data json by request | ||||
|       tags: | ||||
|       - Job add and modify | ||||
|   /api/jobs/edit_meta/{id}: | ||||
|     post: | ||||
|     patch: | ||||
|       consumes: | ||||
|       - application/json | ||||
|       description: |- | ||||
|   | ||||
| @@ -390,8 +390,71 @@ const docTemplate = `{ | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "/api/jobs/edit_meta/": { | ||||
|             "patch": { | ||||
|                 "security": [ | ||||
|                     { | ||||
|                         "ApiKeyAuth": [] | ||||
|                     } | ||||
|                 ], | ||||
|                 "description": "Edit key value pairs in metadata json of job specified by jobID, StartTime and Cluster\nIf a key already exists its content will be overwritten", | ||||
|                 "consumes": [ | ||||
|                     "application/json" | ||||
|                 ], | ||||
|                 "produces": [ | ||||
|                     "application/json" | ||||
|                 ], | ||||
|                 "tags": [ | ||||
|                     "Job add and modify" | ||||
|                 ], | ||||
|                 "summary": "Edit meta-data json by request", | ||||
|                 "parameters": [ | ||||
|                     { | ||||
|                         "description": "Specifies job and payload to add or update", | ||||
|                         "name": "request", | ||||
|                         "in": "body", | ||||
|                         "required": true, | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.JobMetaRequest" | ||||
|                         } | ||||
|                     } | ||||
|                 ], | ||||
|                 "responses": { | ||||
|                     "200": { | ||||
|                         "description": "Updated job resource", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/schema.Job" | ||||
|                         } | ||||
|                     }, | ||||
|                     "400": { | ||||
|                         "description": "Bad Request", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.ErrorResponse" | ||||
|                         } | ||||
|                     }, | ||||
|                     "401": { | ||||
|                         "description": "Unauthorized", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.ErrorResponse" | ||||
|                         } | ||||
|                     }, | ||||
|                     "404": { | ||||
|                         "description": "Job does not exist", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.ErrorResponse" | ||||
|                         } | ||||
|                     }, | ||||
|                     "500": { | ||||
|                         "description": "Internal Server Error", | ||||
|                         "schema": { | ||||
|                             "$ref": "#/definitions/api.ErrorResponse" | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "/api/jobs/edit_meta/{id}": { | ||||
|             "post": { | ||||
|             "patch": { | ||||
|                 "security": [ | ||||
|                     { | ||||
|                         "ApiKeyAuth": [] | ||||
| @@ -1184,6 +1247,37 @@ const docTemplate = `{ | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "api.JobMetaRequest": { | ||||
|             "type": "object", | ||||
|             "required": [ | ||||
|                 "jobId" | ||||
|             ], | ||||
|             "properties": { | ||||
|                 "cluster": { | ||||
|                     "description": "Cluster of job", | ||||
|                     "type": "string", | ||||
|                     "example": "fritz" | ||||
|                 }, | ||||
|                 "jobId": { | ||||
|                     "description": "Cluster Job ID of job", | ||||
|                     "type": "integer", | ||||
|                     "example": 123000 | ||||
|                 }, | ||||
|                 "payload": { | ||||
|                     "description": "Content to Add to Job Meta_Data", | ||||
|                     "allOf": [ | ||||
|                         { | ||||
|                             "$ref": "#/definitions/api.EditMetaRequest" | ||||
|                         } | ||||
|                     ] | ||||
|                 }, | ||||
|                 "startTime": { | ||||
|                     "description": "Start Time of job as epoch", | ||||
|                     "type": "integer", | ||||
|                     "example": 1649723812 | ||||
|                 } | ||||
|             } | ||||
|         }, | ||||
|         "api.JobMetricWithName": { | ||||
|             "type": "object", | ||||
|             "properties": { | ||||
|   | ||||
| @@ -82,7 +82,8 @@ func (api *RestApi) MountApiRoutes(r *mux.Router) { | ||||
| 	r.HandleFunc("/jobs/{id}", api.getCompleteJobById).Methods(http.MethodGet) | ||||
| 	r.HandleFunc("/jobs/tag_job/{id}", api.tagJob).Methods(http.MethodPost, http.MethodPatch) | ||||
| 	r.HandleFunc("/jobs/tag_job/{id}", api.removeTagJob).Methods(http.MethodDelete) | ||||
| 	r.HandleFunc("/jobs/edit_meta/{id}", api.editMeta).Methods(http.MethodPost, http.MethodPatch) | ||||
| 	r.HandleFunc("/jobs/edit_meta/", api.editMetaByRequest).Methods(http.MethodPatch) | ||||
| 	r.HandleFunc("/jobs/edit_meta/{id}", api.editMeta).Methods(http.MethodPatch) | ||||
| 	r.HandleFunc("/jobs/metrics/{id}", api.getJobMetrics).Methods(http.MethodGet) | ||||
| 	r.HandleFunc("/jobs/delete_job/", api.deleteJobByRequest).Methods(http.MethodDelete) | ||||
| 	r.HandleFunc("/jobs/delete_job/{id}", api.deleteJobById).Methods(http.MethodDelete) | ||||
| @@ -98,7 +99,7 @@ func (api *RestApi) MountApiRoutes(r *mux.Router) { | ||||
|  | ||||
| func (api *RestApi) MountUserApiRoutes(r *mux.Router) { | ||||
| 	r.StrictSlash(true) | ||||
| 	// REST API Uses TokenAuth | ||||
| 	// USER REST API Uses TokenAuth | ||||
| 	r.HandleFunc("/jobs/", api.getJobs).Methods(http.MethodGet) | ||||
| 	r.HandleFunc("/jobs/{id}", api.getJobById).Methods(http.MethodPost) | ||||
| 	r.HandleFunc("/jobs/{id}", api.getCompleteJobById).Methods(http.MethodGet) | ||||
| @@ -181,6 +182,14 @@ type EditMetaRequest struct { | ||||
| 	Value string `json:"value" example:"bash script"` | ||||
| } | ||||
|  | ||||
| // JobMetaRequest model | ||||
| type JobMetaRequest struct { | ||||
| 	JobId     *int64          `json:"jobId" validate:"required" example:"123000"` // Cluster Job ID of job | ||||
| 	Cluster   *string         `json:"cluster" example:"fritz"`                    // Cluster of job | ||||
| 	StartTime *int64          `json:"startTime" example:"1649723812"`             // Start Time of job as epoch | ||||
| 	Payload   EditMetaRequest `json:"payload"`                                    // Content to Add to Job Meta_Data | ||||
| } | ||||
|  | ||||
| type TagJobApiRequest []*ApiTag | ||||
|  | ||||
| type GetJobApiRequest []string | ||||
| @@ -609,21 +618,21 @@ func (api *RestApi) getJobById(rw http.ResponseWriter, r *http.Request) { | ||||
| } | ||||
|  | ||||
| // editMeta godoc | ||||
| // @summary    Edit meta-data json | ||||
| // @summary    Edit meta-data json of job identified by database id | ||||
| // @tags Job add and modify | ||||
| // @description Edit key value pairs in job metadata json | ||||
| // @description Edit key value pairs in job metadata json of job specified by database id | ||||
| // @description If a key already exists its content will be overwritten | ||||
| // @accept      json | ||||
| // @produce     json | ||||
| // @param       id      path     int                  true "Job Database ID" | ||||
| // @param       request body     api.EditMetaRequest  true "Kay value pair to add" | ||||
| // @param       request body     api.EditMetaRequest  true "Metadata Key value pair to add or update" | ||||
| // @success     200     {object} schema.Job                "Updated job resource" | ||||
| // @failure     400     {object} api.ErrorResponse         "Bad Request" | ||||
| // @failure     401     {object} api.ErrorResponse         "Unauthorized" | ||||
| // @failure     404     {object} api.ErrorResponse         "Job does not exist" | ||||
| // @failure     500     {object} api.ErrorResponse         "Internal Server Error" | ||||
| // @security    ApiKeyAuth | ||||
| // @router      /api/jobs/edit_meta/{id} [post] | ||||
| // @router      /api/jobs/edit_meta/{id} [patch] | ||||
| func (api *RestApi) editMeta(rw http.ResponseWriter, r *http.Request) { | ||||
| 	id, err := strconv.ParseInt(mux.Vars(r)["id"], 10, 64) | ||||
| 	if err != nil { | ||||
| @@ -653,6 +662,54 @@ func (api *RestApi) editMeta(rw http.ResponseWriter, r *http.Request) { | ||||
| 	json.NewEncoder(rw).Encode(job) | ||||
| } | ||||
|  | ||||
| // editMetaByRequest godoc | ||||
| // @summary    Edit meta-data json of job identified by request | ||||
| // @tags Job add and modify | ||||
| // @description Edit key value pairs in metadata json of job specified by jobID, StartTime and Cluster | ||||
| // @description If a key already exists its content will be overwritten | ||||
| // @accept      json | ||||
| // @produce     json | ||||
| // @param       request body     api.JobMetaRequest   true "Specifies job and payload to add or update" | ||||
| // @success     200     {object} schema.Job                "Updated job resource" | ||||
| // @failure     400     {object} api.ErrorResponse         "Bad Request" | ||||
| // @failure     401     {object} api.ErrorResponse         "Unauthorized" | ||||
| // @failure     404     {object} api.ErrorResponse         "Job does not exist" | ||||
| // @failure     500     {object} api.ErrorResponse         "Internal Server Error" | ||||
| // @security    ApiKeyAuth | ||||
| // @router      /api/jobs/edit_meta/ [patch] | ||||
| func (api *RestApi) editMetaByRequest(rw http.ResponseWriter, r *http.Request) { | ||||
| 	// Parse request body | ||||
| 	req := JobMetaRequest{} | ||||
| 	if err := decode(r.Body, &req); err != nil { | ||||
| 		handleError(fmt.Errorf("parsing request body failed: %w", err), http.StatusBadRequest, rw) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// Fetch job (that will have its meta_data edited) from db | ||||
| 	var job *schema.Job | ||||
| 	var err error | ||||
| 	if req.JobId == nil { | ||||
| 		handleError(errors.New("the field 'jobId' is required"), http.StatusBadRequest, rw) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// log.Printf("loading db job for editMetaByRequest... : JobMetaRequest=%v", req) | ||||
| 	job, err = api.JobRepository.Find(req.JobId, req.Cluster, req.StartTime) | ||||
| 	if err != nil { | ||||
| 		handleError(fmt.Errorf("finding job failed: %w", err), http.StatusUnprocessableEntity, rw) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err := api.JobRepository.UpdateMetadata(job, req.Payload.Key, req.Payload.Value); err != nil { | ||||
| 		http.Error(rw, err.Error(), http.StatusInternalServerError) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	rw.Header().Add("Content-Type", "application/json") | ||||
| 	rw.WriteHeader(http.StatusOK) | ||||
| 	json.NewEncoder(rw).Encode(job) | ||||
| } | ||||
|  | ||||
| // tagJob godoc | ||||
| // @summary     Adds one or more tags to a job | ||||
| // @tags Job add and modify | ||||
|   | ||||
| @@ -473,6 +473,7 @@ func securedCheck(user *schema.User, r *http.Request) error { | ||||
| 		IPAddress = r.RemoteAddr | ||||
| 	} | ||||
|  | ||||
| 	// Cannot Handle ipv6! (e.g. localhost -> [::1]) | ||||
| 	if strings.Contains(IPAddress, ":") { | ||||
| 		IPAddress = strings.Split(IPAddress, ":")[0] | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user