Skip to content

Commit 30e8ae2

Browse files
committed
5.12.2
1 parent a314f04 commit 30e8ae2

59 files changed

Lines changed: 1198 additions & 571 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

documentation/docs/reference/api.md

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ Once generated, copy the key and keep it safe. This key is used to authenticate
3737

3838
``<SNAPSHOT_ID>`` can be retrieved from the URL when you browse a snapshot from the repositories list or from the API when you list snapshots of a repository.
3939

40+
### Global query parameters
41+
42+
- ``normalize`` (optional): when set on a request, all keys in the JSON response are converted to lowercase recursively.
43+
44+
Example:
45+
46+
```bash
47+
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" "https://repomanager.mydomain.net/api/v2/hosts/?normalize"
48+
```
49+
4050

4151
### Source repositories
4252

@@ -396,8 +406,8 @@ Once generated, copy the key and keep it safe. This key is used to authenticate
396406
<tr>
397407
<td>/hosts/package/<code>&lt;PACKAGE&gt;</code>/<code>&lt;VERSION?&gt;</code><br><code>GET</code></td>
398408
<td><code>&lt;APIKEY&gt;</code></td>
399-
<td><code>package</code> (required, in URL)<br><code>version</code> (optional, in URL)<br><code>strict</code> (optional, query parameter)<br><code>strict-name</code> (optional, query parameter)<br><code>strict-version</code> (optional, query parameter)</td>
400-
<td>List hosts that have the specified package installed, optionally filtered by version. By default, package name and version matching can be non-strict. Use <code>strict</code> to enable strict matching for both package name and version, or use <code>strict-name</code> and <code>strict-version</code> independently.</td>
409+
<td><code>package</code> (required, in URL)<br><code>version</code> (optional, in URL)<br><code>strict</code> (optional, query parameter)<br><code>strict-name</code> (optional, query parameter)<br><code>strict-version</code> (optional, query parameter)<br><code>absent</code> (optional, query parameter)</td>
410+
<td>List hosts that have the specified package installed, optionally filtered by version. By default, package name and version matching can be non-strict. Use <code>strict</code> to enable strict matching for both package name and version, or use <code>strict-name</code> and <code>strict-version</code> independently. Set <code>absent</code> to list hosts where the package (and optional version) is not installed.</td>
401411
<td markdown="block">
402412
```bash
403413
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" https://repomanager.mydomain.net/api/v2/hosts/package/nginx
@@ -418,28 +428,44 @@ Once generated, copy the key and keep it safe. This key is used to authenticate
418428
```bash
419429
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" "https://repomanager.mydomain.net/api/v2/hosts/package/nginx/1.24.0-1?strict-version"
420430
```
431+
Return hosts where package is absent:
432+
```bash
433+
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" "https://repomanager.mydomain.net/api/v2/hosts/package/nginx?absent"
434+
```
435+
Return hosts where exact package version is absent:
436+
```bash
437+
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" "https://repomanager.mydomain.net/api/v2/hosts/package/nginx/1.24.0-1?absent&strict"
438+
```
421439
</td>
422440
</tr>
423441
<tr>
424-
<td>/hosts/uptodate<br><code>GET</code></td>
442+
<td>/hosts/uptodate<br>(alias: /hosts/compliant)<br><code>GET</code></td>
425443
<td><code>&lt;APIKEY&gt;</code></td>
426-
<td></td>
427-
<td>List all up-to-date hosts (hosts with no or few available updates based on configured threshold)</td>
444+
<td><code>packages</code> (optional, query parameter)</td>
445+
<td>List all up-to-date (compliant) hosts, i.e. hosts whose pending updates count is below the configured threshold and whose latest update is within the configured threshold (in days). Set the <code>packages</code> query parameter to also include the list of available updates for each host.</td>
428446
<td markdown="block">
429447
```bash
430448
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" https://repomanager.mydomain.net/api/v2/hosts/uptodate
431449
```
450+
Including the list of available updates:
451+
```bash
452+
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" "https://repomanager.mydomain.net/api/v2/hosts/uptodate?packages"
453+
```
432454
</td>
433455
</tr>
434456
<tr>
435-
<td>/hosts/outdated<br><code>GET</code></td>
457+
<td>/hosts/outdated<br>(alias: /hosts/non-compliant)<br><code>GET</code></td>
436458
<td><code>&lt;APIKEY&gt;</code></td>
437-
<td></td>
438-
<td>List all outdated hosts (hosts with available updates exceeding the configured threshold)</td>
459+
<td><code>packages</code> (optional, query parameter)</td>
460+
<td>List all outdated (non-compliant) hosts, i.e. hosts whose pending updates count is greater than or equal to the configured threshold, or whose latest update is older than the configured threshold (in days). Set the <code>packages</code> query parameter to also include the list of available updates for each host.</td>
439461
<td markdown="block">
440462
```bash
441463
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" https://repomanager.mydomain.net/api/v2/hosts/outdated
442464
```
465+
Including the list of available updates:
466+
```bash
467+
curl --fail-with-body -L -s -X GET -H "Authorization: Bearer <APIKEY>" "https://repomanager.mydomain.net/api/v2/hosts/outdated?packages"
468+
```
443469
</td>
444470
</tr>
445471
</tbody>
@@ -574,11 +600,11 @@ Mainly used by the `linupdate` agent, these endpoints allow to register a host t
574600
<tr>
575601
<td>/host/status<br><code>PUT</code></td>
576602
<td><code>&lt;HOST_ID&gt;</code> and <code>&lt;HOST_TOKEN&gt;</code></td>
577-
<td><code>hostname</code> (optional)<br><code>os</code> (optional)<br><code>os_version</code> (optional)<br><code>os_family</code> (optional)<br><code>type</code> (=virtualization type) (optional)<br><code>kernel</code> (optional)<br><code>arch</code> (optional)<br><code>profile</code> (optional)<br><code>env</code> (optional)<br><code>agent_status</code> (optional)<br><code>linupdate_version</code> (optional)<br><code>reboot_required</code> (optional)</td>
603+
<td><code>hostname</code> (optional)<br><code>os</code> (optional)<br><code>os_version</code> (optional)<br><code>os_family</code> (optional)<br><code>type</code> (=virtualization type) (optional)<br><code>kernel</code> (optional)<br><code>arch</code> (optional)<br><code>profile</code> (optional)<br><code>env</code> (optional)<br><code>agent_status</code> (optional)<br><code>agent_version</code> (optional)<br><code>reboot_required</code> (optional)</td>
578604
<td>Send host general information to Repomanager</td>
579605
<td markdown="block">
580606
```bash
581-
curl --fail-with-body --post301 -L -s -X PUT -H "Authorization: Host <HOST_ID>:<HOST_TOKEN>" -H "Content-Type: application/json" -d '{"hostname":"myfqdn.localhost","os":"ubuntu","os_version":"22.04","os_family":"Debian","type":"Bare metal","kernel":"5.15.0-89-generic","arch":"x86_64","profile":"PC","env":"prod","agent_status":"running","linupdate_version":"2.2.2","reboot_required":"false"}' https://repomanager.mydomain.net/api/v2/host/status
607+
curl --fail-with-body --post301 -L -s -X PUT -H "Authorization: Host <HOST_ID>:<HOST_TOKEN>" -H "Content-Type: application/json" -d '{"hostname":"myfqdn.localhost","os":"ubuntu","os_version":"22.04","os_family":"Debian","type":"Bare metal","kernel":"5.15.0-89-generic","arch":"x86_64","profile":"PC","env":"prod","agent_status":"running","agent_version":"2.2.2","reboot_required":"false"}' https://repomanager.mydomain.net/api/v2/host/status
582608
```
583609
</td>
584610
</tr>

www/controllers/Api/Api.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ private static function returnSuccess(array $results): void
177177
// TODO: remove 'return' key in favor of 'rc' key in future major release
178178
$results['return'] = $results['rc'];
179179
$results['note'] = "The 'return' key is deprecated and will be removed in a future major release (replaced by 'rc' key)";
180+
181+
// If the "normalize" query parameter is set, convert all result keys to lowercase
182+
if (isset($_GET['normalize'])) {
183+
$results = Serializer::normalize($results);
184+
}
185+
180186
http_response_code((int) $results['rc']);
181187
echo json_encode($results);
182188
exit;

www/controllers/Api/Host/Host.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,16 @@ public function execute(): array
247247
}
248248

249249
// If linupdate version has been specified then update it in database
250-
if (!empty($this->data['linupdate_version'])) {
250+
if (!empty($this->data['linupdate_version']) or !empty($this->data['agent_version'])) {
251+
// TODO: temporary
252+
# Use agent_version later
253+
if (!empty($this->data['linupdate_version'])) {
254+
$version = $this->data['linupdate_version'];
255+
} else {
256+
$version = $this->data['agent_version'];
257+
}
251258
try {
252-
$hostUpdateController->updateLinupdateVersion($this->hostId, $this->data['linupdate_version']);
259+
$hostUpdateController->updateAgentVersion($this->hostId, $version);
253260
$message[] = "Linupdate version updated successfully.";
254261
} catch (Exception $e) {
255262
throw new Exception('Linupdate version update has failed.');

www/controllers/Api/Hosts/Hosts.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,27 +99,31 @@ public function execute(): array
9999
$strictVersion = true;
100100
}
101101

102+
// If the "absent" query parameter is set, return hosts on which the package is NOT installed
103+
$absent = isset($_GET['absent']);
104+
102105
if (empty($this->uri[5])) {
103106
throw new Exception('You must specify a package');
104107
}
105108

106-
return ['results' => $hostListingController->getByPackage($this->uri[5], $version, $strictName, $strictVersion)];
109+
return ['results' => $hostListingController->getByPackage($this->uri[5], $version, $strictName, $strictVersion, $absent)];
107110
}
108111

109112
/**
110113
* List up-to-date hosts
111114
* https://repomanager.mydomain.net/api/v2/hosts/uptodate
112115
*/
113-
if ($this->uri[4] == 'uptodate' and $this->method == 'GET') {
114-
return ['results' => $hostListingController->getUpToDate()];
116+
if (in_array($this->uri[4], ['uptodate', 'compliant']) and $this->method == 'GET') {
117+
return ['results' => $hostListingController->getUpToDate(isset($_GET['packages']))];
115118
}
116119

117120
/**
118121
* List outdated hosts
119122
* https://repomanager.mydomain.net/api/v2/hosts/outdated
120123
*/
121-
if ($this->uri[4] == 'outdated' and $this->method == 'GET') {
122-
return ['results' => $hostListingController->getOutdated()];
124+
if (in_array($this->uri[4], ['outdated', 'non-compliant']) and $this->method == 'GET') {
125+
// Also get the list of available updates if the "list" query parameter is set
126+
return ['results' => $hostListingController->getOutdated(isset($_GET['packages']))];
123127
}
124128
}
125129

www/controllers/Api/Serializer.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Controllers\Api;
4+
5+
class Serializer
6+
{
7+
/**
8+
* Recursively normalize the keys of an array to lowercase
9+
* so that the API always returns a consistent key format, no matter
10+
* whether the data comes from the database (PascalCase columns) or
11+
* is built by the backend (lowercase keys).
12+
*/
13+
public static function normalize($data)
14+
{
15+
// Only arrays have keys to normalize, return scalars as-is
16+
if (!is_array($data)) {
17+
return $data;
18+
}
19+
20+
$result = [];
21+
22+
foreach ($data as $key => $value) {
23+
// Recursively normalize nested arrays
24+
$value = self::normalize($value);
25+
26+
// Numeric keys (sequential lists) are kept as-is
27+
if (is_int($key)) {
28+
$result[$key] = $value;
29+
continue;
30+
}
31+
32+
$result[strtolower($key)] = $value;
33+
}
34+
35+
return $result;
36+
}
37+
}

www/controllers/Filesystem/Directory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Directory
1010
* Return an array with the list of founded directories in specified directory path
1111
* Directory name can be filtered with a regex
1212
*/
13-
public static function findRecursive(string $directoryPath, string $directoryNameRegex = null, bool $returnFullPath = true) : array
13+
public static function findRecursive(string $directoryPath, string $directoryNameRegex = '', bool $returnFullPath = true) : array
1414
{
1515
$foundedDirs = [];
1616

www/controllers/Host/Export.php

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ public function export(array $hosts): string
1818
throw new Exception('No hosts provided for export');
1919
}
2020

21-
/**
22-
* First check that hosts Id are valid and exist
23-
*/
21+
// First check that hosts Id are valid and exist
2422
foreach ($hosts as $id) {
2523
if (!is_numeric($id)) {
2624
throw new Exception('Invalid host Id: ' . $id);
@@ -31,9 +29,7 @@ public function export(array $hosts): string
3129
}
3230
}
3331

34-
/**
35-
* Generate the CSV header
36-
*/
32+
// Generate the CSV header
3733
$csv[] = [
3834
'Id',
3935
'Hostname',
@@ -53,9 +49,7 @@ public function export(array $hosts): string
5349
'Reboot required',
5450
];
5551

56-
/**
57-
* For each host, get its information and add it to the CSV array
58-
*/
52+
// For each host, get its information and add it to the CSV array
5953
foreach ($hosts as $id) {
6054
$data = $this->get($id);
6155

@@ -74,14 +68,12 @@ public function export(array $hosts): string
7468
$data['Online_status'],
7569
$data['Online_status_date'],
7670
$data['Online_status_time'],
77-
$data['Linupdate_version'],
71+
$data['Agent_version'],
7872
$data['Reboot_required'],
7973
];
8074
}
8175

82-
/**
83-
* Encode to JSON and return the CSV data
84-
*/
76+
// Encode to JSON and return the CSV data
8577
try {
8678
return json_encode($csv, JSON_THROW_ON_ERROR);
8779
} catch (JsonException $e) {

www/controllers/Host/Host.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,22 +87,22 @@ public function getSettings(): array
8787
/**
8888
* Edit the display settings on the hosts page
8989
*/
90-
public function setSettings(int $packagesConsideredOutdated, int $packagesConsideredCritical): void
90+
public function setSettings(int $complianceThresholdCount, int $complianceThresholdDays): void
9191
{
9292
if (!HostPermission::allowedAction('edit-settings')) {
9393
throw new Exception('You are not allowed to perform this action');
9494
}
9595

96-
if (!is_numeric($packagesConsideredOutdated) or !is_numeric($packagesConsideredCritical)) {
96+
if (!is_numeric($complianceThresholdCount) or !is_numeric($complianceThresholdDays)) {
9797
throw new Exception('Parameters must be numeric');
9898
}
9999

100-
// Parameters must be greater than 0
101-
if ($packagesConsideredOutdated <= 0 or $packagesConsideredCritical <= 0) {
102-
throw new Exception('Parameters must be greater than 0');
100+
// Value must be greater than 0
101+
if ($complianceThresholdCount <= 0 or $complianceThresholdDays <= 0) {
102+
throw new Exception('Value must be greater than 0');
103103
}
104104

105-
$this->model->setSettings($packagesConsideredOutdated, $packagesConsideredCritical);
105+
$this->model->setSettings($complianceThresholdCount, $complianceThresholdDays);
106106
}
107107

108108
/**

0 commit comments

Comments
 (0)