mirror of
https://github.com/Cacti/cacti.git
synced 2026-10-23 03:27:02 +09:00
Fix dsstats partition dispatch and profile retention fallbacks (#8304)
* fix(core): preserve dsstats type and render retention fallbacks Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * test(auth): use certificate expiry truth in rendering assertions Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
This commit is contained in:
1 parent
af9d1591a3
commit
76579e6292
10 files changed
+97
-1
No files matched your search
@@ -213,6 +213,7 @@ function color_import_processor(array &$colors) : array {
|
||||
switch ($line_item) {
|
||||
case 'hex':
|
||||
$hexcol = $j;
|
||||
// Fall through: retain the hex column alongside the name column.
|
||||
case 'name':
|
||||
if (!$first_column) {
|
||||
$save_order .= ', ';
|
||||
|
||||
@@ -129,6 +129,7 @@ switch (grv('action')) {
|
||||
case 'runall':
|
||||
debug_runall_filtered();
|
||||
|
||||
// Fall through: render the refreshed list after running the selected sources.
|
||||
default:
|
||||
$refresh = [
|
||||
'seconds' => grv('refresh'),
|
||||
|
||||
@@ -1141,7 +1141,8 @@ function profile_edit() : void {
|
||||
form_selectable_cell(filter_value($rra['name'], '', $url), $i);
|
||||
|
||||
form_selectable_cell('<em>' . get_span($profile['step'] * $rra['steps'] * $rra['rows']) . '</em>', $i);
|
||||
form_selectable_cell('<em>' . isset($timespans[$rra['timespan']]) ? $timespans[$rra['timespan']] : get_span($rra['timespan']) . '</em>', $i); // @phpstan-ignore-line
|
||||
$retention = $timespans[$rra['timespan']] ?? get_span($rra['timespan']);
|
||||
form_selectable_cell('<em>' . $retention . '</em>', $i);
|
||||
form_selectable_cell('<em>' . $rra['steps'] . '</em>', $i);
|
||||
form_selectable_cell('<em>' . $rra['rows'] . '</em>', $i);
|
||||
|
||||
|
||||
@@ -204,6 +204,7 @@ switch (grv('action')) {
|
||||
case 'unlock':
|
||||
$_SESSION['sess_graph_lock_id'] = gfrv('id');
|
||||
$_SESSION['sess_graph_locked'] = (grv('action') == 'lock' ? true : false);
|
||||
// Fall through: show the editor with the new lock state.
|
||||
case 'graph_edit':
|
||||
top_header();
|
||||
graph_edit();
|
||||
|
||||
@@ -1290,6 +1290,7 @@ function aggregate_create_update(int &$local_graph_id, array $member_graphs, arr
|
||||
(local_graph_id, graph_type_id, consolidation_function_id, text_format, value, hard_return, gprint_id, sequence)
|
||||
VALUES (?, 1, ?, '', '', 'on', 2, ?)", [$local_graph_id, $cf_id, $next_item_sequence++]);
|
||||
|
||||
// Fall through: all totals also need the common totalling graph items.
|
||||
case AGGREGATE_TOTAL_ONLY:
|
||||
// use the prefix for totalling GPRINTs as given by the user
|
||||
switch ($_total_type) {
|
||||
|
||||
@@ -2200,8 +2200,10 @@ function memory_bytes(mixed $val) : mixed {
|
||||
switch($last) {
|
||||
case 'g':
|
||||
$val *= 1024;
|
||||
// Fall through: gigabytes also need the megabyte and kilobyte multipliers.
|
||||
case 'm':
|
||||
$val *= 1024;
|
||||
// Fall through: megabytes also need the kilobyte multiplier.
|
||||
case 'k':
|
||||
$val *= 1024;
|
||||
}
|
||||
|
||||
@@ -85,6 +85,12 @@ if (cacti_sizeof($parms)) {
|
||||
case '--partition':
|
||||
$fpartition = true;
|
||||
|
||||
// Preserve the legacy --partition=TYPE spelling for QA callers.
|
||||
if ($value !== '') {
|
||||
$type = $value;
|
||||
}
|
||||
|
||||
break;
|
||||
case '--type':
|
||||
$type = $value;
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ switch(grv('action')) {
|
||||
|
||||
rrdcheck_purge();
|
||||
|
||||
// Fall through: display the remaining problems after purging.
|
||||
default:
|
||||
rrdcheck_display_problems();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
// Copyright (C) 2004-2026 The Cacti Group. GPL-2.0-or-later.
|
||||
|
||||
test('dsstats partition options retain the selected collector type', function (array $parameters, string $expectedType, bool $expectedPartition) {
|
||||
$source = file_get_contents(dirname(__DIR__, 4) . '/poller_dsstats.php');
|
||||
$parser = (new \PhpParser\ParserFactory())->createForNewestSupportedVersion();
|
||||
$nodes = $parser->parse($source);
|
||||
$block = (new \PhpParser\NodeFinder())->findFirst($nodes, static function ($node) {
|
||||
return $node instanceof \PhpParser\Node\Stmt\If_ &&
|
||||
$node->cond instanceof \PhpParser\Node\Expr\FuncCall &&
|
||||
$node->cond->name instanceof \PhpParser\Node\Name &&
|
||||
$node->cond->name->toString() === 'cacti_sizeof' &&
|
||||
$node->cond->args[0]->value instanceof \PhpParser\Node\Expr\Variable &&
|
||||
$node->cond->args[0]->value->name === 'parms';
|
||||
});
|
||||
expect($block)->not->toBeNull();
|
||||
$fragment = substr($source, $block->getStartFilePos(), $block->getEndFilePos() - $block->getStartFilePos() + 1);
|
||||
|
||||
// Execute the actual repository argument parser, before DB/poller work.
|
||||
$parse = static function (array $parms) use ($fragment) : array {
|
||||
$debug = false;
|
||||
$force = false;
|
||||
$fpartition = false;
|
||||
$type = 'pmaster';
|
||||
$thread_id = 0;
|
||||
eval($fragment);
|
||||
|
||||
return [$type, $fpartition];
|
||||
};
|
||||
|
||||
expect($parse($parameters))->toBe([$expectedType, $expectedPartition]);
|
||||
})->with([
|
||||
'no partition request' => [[], 'pmaster', false],
|
||||
'bare long option' => [['--partition'], 'pmaster', true],
|
||||
'bare short option' => [['-p'], 'pmaster', true],
|
||||
'type before partition' => [['--type=bmaster', '--partition'], 'bmaster', true],
|
||||
'type after partition' => [['--partition', '--type=dmaster'], 'dmaster', true],
|
||||
'legacy partition type' => [['--partition=bmaster'], 'bmaster', true],
|
||||
'legacy short partition type' => [['-p=dmaster'], 'dmaster', true],
|
||||
]);
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
// Copyright (C) 2004-2026 The Cacti Group. GPL-2.0-or-later.
|
||||
|
||||
test('profile retention labels choose the configured or computed span and retain emphasis', function (?string $configuredLabel) {
|
||||
$source = file_get_contents(dirname(__DIR__, 4) . '/data_source_profiles.php');
|
||||
$parser = (new \PhpParser\ParserFactory())->createForNewestSupportedVersion();
|
||||
$nodes = $parser->parse($source);
|
||||
$finder = new \PhpParser\NodeFinder();
|
||||
$printer = new \PhpParser\PrettyPrinter\Standard();
|
||||
$spanFunction = $finder->findFirst($nodes, static fn ($node) => $node instanceof \PhpParser\Node\Stmt\Function_ && $node->name->toString() === 'get_span');
|
||||
expect($spanFunction)->not->toBeNull();
|
||||
// Bind the actual page-local get_span body as a closure; never shadow core functions.
|
||||
$spanNode = new \PhpParser\Node\Expr\Closure([
|
||||
'params' => $spanFunction->params, 'stmts' => $spanFunction->stmts,
|
||||
'returnType' => $spanFunction->returnType,
|
||||
]);
|
||||
$span = eval('return ' . $printer->prettyPrintExpr($spanNode) . ';');
|
||||
$assignment = $finder->findFirst($nodes, static fn ($node) => $node instanceof \PhpParser\Node\Expr\Assign &&
|
||||
$node->var instanceof \PhpParser\Node\Expr\Variable && $node->var->name === 'retention');
|
||||
$call = $finder->findFirst($nodes, static function ($node) use ($printer) {
|
||||
return $node instanceof \PhpParser\Node\Expr\FuncCall &&
|
||||
$node->name instanceof \PhpParser\Node\Name &&
|
||||
$node->name->toString() === 'form_selectable_cell' &&
|
||||
preg_match('/\$(timespans|retention)\b/', $printer->prettyPrintExpr($node->args[0]->value));
|
||||
});
|
||||
expect($call)->not->toBeNull();
|
||||
|
||||
// Route only the page-local dependency to its production closure.
|
||||
foreach ($finder->findInstanceOf($nodes, \PhpParser\Node\Expr\FuncCall::class) as $dependency) {
|
||||
if ($dependency->name instanceof \PhpParser\Node\Name && $dependency->name->toString() === 'get_span') {
|
||||
$dependency->name = new \PhpParser\Node\Expr\Variable('span');
|
||||
}
|
||||
}
|
||||
$rra = ['timespan' => 7200];
|
||||
$timespans = $configuredLabel === null ? [] : [7200 => $configuredLabel];
|
||||
|
||||
if ($assignment !== null) {
|
||||
eval($printer->prettyPrintExpr($assignment) . ';');
|
||||
}
|
||||
$result = eval('return ' . $printer->prettyPrintExpr($call->args[0]->value) . ';');
|
||||
expect($result)->toBe('<em>' . ($configuredLabel ?? '2 Hours') . '</em>');
|
||||
})->with(['configured span' => ['Configured span'], 'computed span' => [null]]);
|
||||
Reference in new issue
Block a user