From 970ad4ff696405b78bc43abd2cd431049c4ffb68 Mon Sep 17 00:00:00 2001 From: Marcin Haba Date: Thu, 1 Dec 2022 14:43:24 +0100 Subject: [PATCH] baculum: Add sources endpoint --- .../protected/API/Modules/Database.php | 3 + .../protected/API/Modules/SourceManager.php | 81 +++++++++++ .../protected/API/Modules/SourceRecord.php | 46 ++++++ .../protected/API/Pages/API/Sources.php | 104 ++++++++++++++ .../protected/API/Pages/API/config.xml | 1 + .../protected/API/Pages/API/endpoints.xml | 2 + .../protected/API/openapi_baculum.json | 136 ++++++++++++++++++ .../Common/Modules/Errors/SourceError.php | 33 +++++ 8 files changed, 406 insertions(+) create mode 100644 gui/baculum/protected/API/Modules/SourceManager.php create mode 100644 gui/baculum/protected/API/Modules/SourceRecord.php create mode 100644 gui/baculum/protected/API/Pages/API/Sources.php create mode 100644 gui/baculum/protected/Common/Modules/Errors/SourceError.php diff --git a/gui/baculum/protected/API/Modules/Database.php b/gui/baculum/protected/API/Modules/Database.php index fc80a9752..a94248dcc 100644 --- a/gui/baculum/protected/API/Modules/Database.php +++ b/gui/baculum/protected/API/Modules/Database.php @@ -191,6 +191,9 @@ class Database extends APIModule { $cond[] = "{$key} {$value[$i]['operator']} :{$kval}{$i}"; $vals[":{$kval}{$i}"] = $value[$i]['vals']; $value[$i]['operator'] = ''; + } elseif (in_array($value[$i]['operator'], ['IS', 'IS NOT'])) { + $cond[] = "{$key} {$value[$i]['operator']} {$value[$i]['vals']}"; + $value[$i]['operator'] = ''; } else { $cond[] = "$key = :{$kval}{$i}"; $vals[":{$kval}{$i}"] = $value[$i]['vals']; diff --git a/gui/baculum/protected/API/Modules/SourceManager.php b/gui/baculum/protected/API/Modules/SourceManager.php new file mode 100644 index 000000000..b1d023941 --- /dev/null +++ b/gui/baculum/protected/API/Modules/SourceManager.php @@ -0,0 +1,81 @@ + + * @category Module + * @package Baculum API + */ +class SourceManager extends APIModule { + + public function getSources($criteria = [], $limit_val = null) { + $limit = ''; + if(is_int($limit_val) && $limit_val > 0) { + $limit = ' LIMIT ' . $limit_val; + } + $where = Database::getWhere($criteria, true); + $sql = 'SELECT + sres.fileset, sres.client, sres.job, ores.starttime, ores.jobid, jres.jobstatus + FROM Job AS jres, + ( + SELECT DISTINCT + FileSet.FileSet AS fileset, + Client.Name AS client, + Job.Name AS job + FROM Job + JOIN FileSet USING (FileSetId) + JOIN Client USING (ClientId) + ) AS sres, ( + SELECT + MAX(StartTime) AS starttime, + MAX(JobId) AS jobid, + FileSet.FileSet AS fileset, + Client.Name AS client, + Job.Name AS job + FROM Job + JOIN FileSet USING (FileSetId) + JOIN Client USING (ClientId) + GROUP BY FileSet.FileSet, Client.Name, Job.Name + ) AS ores + LEFT JOIN Object USING (JobId) + WHERE + jres.JobId = ores.jobid + AND sres.job = ores.job + AND sres.client = ores.client + AND sres.fileset = ores.fileset + AND jres.Type = \'B\' + ' . (!empty($where['where']) ? ' AND ' . $where['where'] : '') . ' + ORDER BY sres.fileset ASC, sres.client ASC, sres.job ASC, ores.starttime ASC ' . $limit; + + $connection = SourceRecord::finder()->getDbConnection(); + $connection->setActive(true); + $pdo = $connection->getPdoInstance(); + $sth = $pdo->prepare($sql); + $sth->execute($where['params']); + return $sth->fetchAll(\PDO::FETCH_ASSOC); + } +} +?> diff --git a/gui/baculum/protected/API/Modules/SourceRecord.php b/gui/baculum/protected/API/Modules/SourceRecord.php new file mode 100644 index 000000000..0bb3c379b --- /dev/null +++ b/gui/baculum/protected/API/Modules/SourceRecord.php @@ -0,0 +1,46 @@ + + * @category Database + * @package Baculum API + */ +class SourceRecord extends APIDbModule { + + const TABLE = 'Job'; + + public $fileset; + public $client; + public $job; + public $endtime; + public $jobid; + public $jobstatus; + + public static function finder($className = __CLASS__) { + return parent::finder($className); + } +} diff --git a/gui/baculum/protected/API/Pages/API/Sources.php b/gui/baculum/protected/API/Pages/API/Sources.php new file mode 100644 index 000000000..450469838 --- /dev/null +++ b/gui/baculum/protected/API/Pages/API/Sources.php @@ -0,0 +1,104 @@ + + * @category API + * @package Baculum API + */ +class Sources extends BaculumAPIServer { + + public function get() { + $misc = $this->getModule('misc'); + $limit = $this->Request->contains('limit') ? (int)$this->Request['limit'] : 0; + $job = $this->Request->contains('job') && $misc->isValidName($this->Request['job']) ? $this->Request['job'] : ''; + $client = $this->Request->contains('client') && $misc->isValidName($this->Request['client']) ? $this->Request['client'] : ''; + $fileset = $this->Request->contains('fileset') && $misc->isValidName($this->Request['fileset']) ? $this->Request['fileset'] : ''; + $starttime_from = $this->Request->contains('starttime_from') && $misc->isValidInteger($this->Request['starttime_from']) ? (int)$this->Request['starttime_from'] : null; + $starttime_to = $this->Request->contains('starttime_to') && $misc->isValidInteger($this->Request['starttime_to']) ? (int)$this->Request['starttime_to'] : null; + $jobstatus = $this->Request->contains('jobstatus') && $misc->isValidState($this->Request['jobstatus']) ? $this->Request['jobstatus'] : ''; + $hasobject = $this->Request->contains('hasobject') && $misc->isValidBoolean($this->Request['hasobject']) ? $this->Request['hasobject'] : null; + + // @TODO: Fix using sres and jres in this place. It can lead to a problem when sres or jres will be changed in manager. + $params = []; + if (!empty($job)) { + $params['sres.job'] = [[ + 'vals' => $job + ]]; + } + if (!empty($client)) { + $params['sres.client'] = [[ + 'vals' => $client + ]]; + } + if (!empty($fileset)) { + $params['sres.fileset'] = [[ + 'vals' => $fileset + ]]; + } + if (!empty($jobstatus)) { + $params['jres.jobstatus'] = [[ + 'vals' => $jobstatus + ]]; + } + if (!is_null($hasobject)) { + if ($misc->isValidBooleanTrue($hasobject)) { + $params['Object.ObjectId'][] = [ + 'operator' => 'IS NOT', + 'vals' => 'NULL' + ]; + } elseif ($misc->isValidBooleanFalse($hasobject)) { + $params['Object.ObjectId'][] = [ + 'operator' => 'IS', + 'vals' => 'NULL' + ]; + } + } + + // Start time range + if (!empty($starttime_from) || !empty($starttime_to)) { + $params['ores.starttime'] = []; + if (!empty($starttime_from)) { + $params['ores.starttime'][] = [ + 'operator' => '>=', + 'vals' => date('Y-m-d H:i:s', $starttime_from) + ]; + } + if (!empty($starttime_to)) { + $params['ores.starttime'][] = [ + 'operator' => '<=', + 'vals' => date('Y-m-d H:i:s', $starttime_to) + ]; + } + } + + $sources = $this->getModule('source')->getSources($params, $limit); + $this->output = $sources; + $this->error = SourceError::ERROR_NO_ERRORS; + } +} +?> diff --git a/gui/baculum/protected/API/Pages/API/config.xml b/gui/baculum/protected/API/Pages/API/config.xml index 56e6ccd5e..bc367f080 100644 --- a/gui/baculum/protected/API/Pages/API/config.xml +++ b/gui/baculum/protected/API/Pages/API/config.xml @@ -30,6 +30,7 @@ + diff --git a/gui/baculum/protected/API/Pages/API/endpoints.xml b/gui/baculum/protected/API/Pages/API/endpoints.xml index ae505ad03..9cce05234 100644 --- a/gui/baculum/protected/API/Pages/API/endpoints.xml +++ b/gui/baculum/protected/API/Pages/API/endpoints.xml @@ -100,6 +100,8 @@ + + diff --git a/gui/baculum/protected/API/openapi_baculum.json b/gui/baculum/protected/API/openapi_baculum.json index e31e84ec7..90ebede5e 100644 --- a/gui/baculum/protected/API/openapi_baculum.json +++ b/gui/baculum/protected/API/openapi_baculum.json @@ -132,6 +132,15 @@ "Object": { "$ref": "#/definitions/Object" }, + "Sources": { + "type": "array", + "items": { + "$ref": "#/definitions/Source" + } + }, + "Source": { + "$ref": "#/definitions/Source" + }, "Events": { "type": "array", "items": { @@ -6782,6 +6791,104 @@ ] } }, + "/api/v2/sources": { + "get": { + "tags": ["sources"], + "summary": "Source list", + "description": "Get source list.", + "responses": { + "200": { + "description": "List of sources", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "output": { + "$ref": "#/components/schemas/Sources" + }, + "error": { + "type": "integer", + "description": "Error code", + "enum": [0, 1, 2, 3, 6, 7, 1000] + } + } + } + } + } + } + }, + "parameters": [ + { + "$ref": "#/components/parameters/Limit" + }, + { + "name": "job", + "in": "query", + "required": false, + "description": "Job name filter", + "schema": { + "type": "string" + } + }, + { + "name": "client", + "in": "query", + "required": false, + "description": "Client name filter", + "schema": { + "type": "string" + } + }, + { + "name": "fileset", + "in": "query", + "required": false, + "description": "Fileset name filter", + "schema": { + "type": "string" + } + }, + { + "name": "starttime_from", + "in": "query", + "required": false, + "description": "Start time from (UNIX timestamp format, seconds)", + "schema": { + "type": "integer" + } + }, + { + "name": "starttime_to", + "in": "query", + "required": false, + "description": "Start time to (UNIX timestamp format, seconds)", + "schema": { + "type": "integer" + } + }, + { + "name": "jobstatus", + "in": "query", + "required": false, + "description": "Job status letter", + "schema": { + "type": "string", + "enum": ["C", "R", "B", "T", "W", "E", "e", "f", "D", "A", "I", "F", "S", "m", "M", "s", "j", "c", "d", "t", "p", "i", "a", "l", "L"] + } + }, + { + "name": "hasobject", + "in": "query", + "required": false, + "description": "Show sources that have object, 1 - show sources with objects created, 0 - show sources without objects created", + "schema": { + "type": "boolean" + } + } + ] + } + }, "/api/v2/events": { "get": { "tags": ["events"], @@ -8209,6 +8316,35 @@ } } }, + "Source": { + "type": "object", + "properties": { + "fileset": { + "description": "Fileset name", + "type": "string" + }, + "client": { + "description": "Client name", + "type": "string" + }, + "job": { + "description": "Job name", + "type": "string" + }, + "starttime": { + "description": "Start time latest job using this source", + "type": "string" + }, + "jobid": { + "description": "Latest jobid", + "type": "integer" + }, + "jobstatus": { + "description": "Job status latest job", + "type": "string" + } + } + }, "Event": { "type": "object", "properties": { diff --git a/gui/baculum/protected/Common/Modules/Errors/SourceError.php b/gui/baculum/protected/Common/Modules/Errors/SourceError.php new file mode 100644 index 000000000..779b8be5b --- /dev/null +++ b/gui/baculum/protected/Common/Modules/Errors/SourceError.php @@ -0,0 +1,33 @@ + + * @category Errors + * @package Baculum Common + */ +class SourceError extends GenericError { +} -- 2.47.3