Toggle the script in the orchestrator you clicked, not the first one that lists it
docker_update.sh runs bare in daily, --weekly in weekly and --remainder in monthly, so switching it off in monthly disabled the daily run and reported success.
This commit is contained in:
@@ -76,11 +76,24 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|||||||
|
|
||||||
$id = trim($_POST['id'] ?? '');
|
$id = trim($_POST['id'] ?? '');
|
||||||
$enabled = ($_POST['enabled'] ?? '0') === '1';
|
$enabled = ($_POST['enabled'] ?? '0') === '1';
|
||||||
|
// Which orchestrator's list this click came from. Optional for callers that have only one, but
|
||||||
|
// the scheduler always sends it: without it the toggle acts on whichever array declares the
|
||||||
|
// script first, which for a script listed in three is right by luck at best.
|
||||||
|
$array = trim($_POST['array'] ?? '');
|
||||||
|
|
||||||
if (!$id || !preg_match('/^[a-zA-Z0-9_.\/\-]+\.sh$/', $id) || str_contains($id, '..')) {
|
if (!$id || !preg_match('/^[a-zA-Z0-9_.\/\-]+\.sh$/', $id) || str_contains($id, '..')) {
|
||||||
echo json_encode(['ok' => false, 'error' => 'Invalid id']);
|
echo json_encode(['ok' => false, 'error' => 'Invalid id']);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ok = vv_conf_toggle_script($id, $enabled);
|
// Shaped like the arrays it may name and nothing else. It is compared against array names read
|
||||||
|
// out of master.conf rather than used to build a pattern, but a value that cannot be an array
|
||||||
|
// name has no legitimate target and is refused rather than quietly ignored — silently falling
|
||||||
|
// back to first-match is how this went wrong in the first place.
|
||||||
|
if ($array !== '' && !preg_match('/^[A-Z][A-Z0-9_]*_SCRIPTS$/', $array)) {
|
||||||
|
echo json_encode(['ok' => false, 'error' => 'Invalid array']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ok = vv_conf_toggle_script($id, $enabled, $array !== '' ? $array : null);
|
||||||
echo json_encode(['ok' => $ok, 'error' => $ok ? null : 'Failed to write master.conf']);
|
echo json_encode(['ok' => $ok, 'error' => $ok ? null : 'Failed to write master.conf']);
|
||||||
|
|||||||
@@ -618,18 +618,31 @@ function vv_conf_flag_set(string $name, bool $value): bool {
|
|||||||
}, [$name => $val]);
|
}, [$name => $val]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comment or uncomment a script's line in the first master.conf array that contains it.
|
// Comment or uncomment a script's line in one master.conf array.
|
||||||
|
//
|
||||||
|
// $array names which one. It is optional only so existing single-array callers keep working;
|
||||||
|
// without it this toggles the FIRST array containing the script, which is wrong whenever a script
|
||||||
|
// is listed in more than one — and several are, deliberately. docker_update.sh runs bare in daily,
|
||||||
|
// --weekly in weekly and --remainder in monthly, so turning it off in monthly silently disabled
|
||||||
|
// the daily run instead and left monthly on: the exact inverse of what was asked for, with a
|
||||||
|
// success reported. Callers that know their array must pass it.
|
||||||
|
//
|
||||||
// Goes through vv_conf_edit() for the lock, the pre-write backup, the syntax check and the audit
|
// Goes through vv_conf_edit() for the lock, the pre-write backup, the syntax check and the audit
|
||||||
// line — see vv_conf_flag_set() above for what that replaced. There is no key to verify here,
|
// line — see vv_conf_flag_set() above for what that replaced. There is no key to verify here,
|
||||||
// so the audit subject is the script id and a clean source is the whole assertion.
|
// so the audit subject is the script id and a clean source is the whole assertion.
|
||||||
function vv_conf_toggle_script(string $rel, bool $enable): bool {
|
function vv_conf_toggle_script(string $rel, bool $enable, ?string $array = null): bool {
|
||||||
return vv_conf_edit('master.conf', function (string $content) use ($rel, $enable): ?string {
|
return vv_conf_edit('master.conf', function (string $content) use ($rel, $enable, $array): ?string {
|
||||||
$lines = preg_split('/(?<=\n)/', $content) ?: [];
|
$lines = preg_split('/(?<=\n)/', $content) ?: [];
|
||||||
$changed = false;
|
$changed = false;
|
||||||
$inArray = false;
|
$inArray = false;
|
||||||
$relEsc = preg_quote($rel, '/');
|
$relEsc = preg_quote($rel, '/');
|
||||||
foreach ($lines as &$line) {
|
foreach ($lines as &$line) {
|
||||||
if (preg_match('/^\s*[A-Z_]+_SCRIPTS\s*=\s*\(/', $line)) $inArray = true;
|
if (preg_match('/^\s*([A-Z_]+_SCRIPTS)\s*=\s*\(/', $line, $am)) {
|
||||||
|
// Only the named array is entered when one was named. Everything else is skipped
|
||||||
|
// wholesale rather than matched and rejected per line, so a script that appears in
|
||||||
|
// three arrays cannot be reached in the two it was not clicked in.
|
||||||
|
$inArray = ($array === null || $am[1] === $array);
|
||||||
|
}
|
||||||
if ($inArray && preg_match('/^\s*\)\s*(?:#.*)?$/', $line) && !str_contains($line, '(')) $inArray = false;
|
if ($inArray && preg_match('/^\s*\)\s*(?:#.*)?$/', $line) && !str_contains($line, '(')) $inArray = false;
|
||||||
if (!$inArray) continue;
|
if (!$inArray) continue;
|
||||||
if (!preg_match('/^\s*(?:#\s*)?"' . $relEsc . '(?:\s[^"]*)?"/', $line)) continue;
|
if (!preg_match('/^\s*(?:#\s*)?"' . $relEsc . '(?:\s[^"]*)?"/', $line)) continue;
|
||||||
@@ -669,7 +682,14 @@ function vv_script_children(string $orchPath, array $schedule): array {
|
|||||||
$rsyncFlagName = $rm[1] . '_RSYNC_ENABLED';
|
$rsyncFlagName = $rm[1] . '_RSYNC_ENABLED';
|
||||||
}
|
}
|
||||||
|
|
||||||
$addChild = function(string $rel) use ($scriptsDir, $schedule, $confMap, &$children, &$seen) {
|
// $fromArray is the array this orchestrator actually iterates. It matters because a script
|
||||||
|
// may be listed in several with different arguments — docker_update.sh runs bare in daily,
|
||||||
|
// --weekly in weekly and --remainder in monthly — and vv_conf_script_map() keeps only the
|
||||||
|
// first it meets, so the map would label the monthly child DAILY_MAINTENANCE_SCRIPTS. Every
|
||||||
|
// consumer of conf_array then acts on the wrong line: the toggle disabled daily when monthly
|
||||||
|
// was clicked, and the drag reorder read the wrong list.
|
||||||
|
$addChild = function(string $rel, ?string $fromArray = null)
|
||||||
|
use ($scriptsDir, $schedule, $confMap, &$children, &$seen) {
|
||||||
if (isset($seen[$rel]) || !file_exists("$scriptsDir/$rel")) return;
|
if (isset($seen[$rel]) || !file_exists("$scriptsDir/$rel")) return;
|
||||||
$seen[$rel] = true;
|
$seen[$rel] = true;
|
||||||
$entry = $schedule[$rel] ?? ['enabled' => false, 'cron' => ''];
|
$entry = $schedule[$rel] ?? ['enabled' => false, 'cron' => ''];
|
||||||
@@ -685,7 +705,9 @@ function vv_script_children(string $orchPath, array $schedule): array {
|
|||||||
'log_enabled' => (bool)($entry['log_enabled'] ?? false),
|
'log_enabled' => (bool)($entry['log_enabled'] ?? false),
|
||||||
'conf_managed' => $conf['managed'],
|
'conf_managed' => $conf['managed'],
|
||||||
'conf_enabled' => $conf['enabled'], // null if not in any *_SCRIPTS array
|
'conf_enabled' => $conf['enabled'], // null if not in any *_SCRIPTS array
|
||||||
'conf_array' => $conf['array'],
|
// The array this orchestrator reads, when we know it. Falling back to the map is only
|
||||||
|
// for children found as static paths, which are not array members at all.
|
||||||
|
'conf_array' => $fromArray ?? $conf['array'],
|
||||||
'suggested_cron' => $suggested['cron'],
|
'suggested_cron' => $suggested['cron'],
|
||||||
'suggested_label' => $suggested['label'],
|
'suggested_label' => $suggested['label'],
|
||||||
];
|
];
|
||||||
@@ -703,7 +725,7 @@ function vv_script_children(string $orchPath, array $schedule): array {
|
|||||||
if (!empty($refs[1])) {
|
if (!empty($refs[1])) {
|
||||||
$confRaw = file_get_contents(CONF_DIR . '/master.conf') ?: '';
|
$confRaw = file_get_contents(CONF_DIR . '/master.conf') ?: '';
|
||||||
foreach (array_unique($refs[1]) as $varName) {
|
foreach (array_unique($refs[1]) as $varName) {
|
||||||
foreach (vv_parse_conf_array_full($confRaw, $varName) as $item) $addChild($item['path']);
|
foreach (vv_parse_conf_array_full($confRaw, $varName) as $item) $addChild($item['path'], $varName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1782,7 +1782,11 @@ function vvSaveChild(el) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (orchOn) {
|
if (orchOn) {
|
||||||
vvPost('/plugins/varaverk/api/conf_toggle.php', {id, enabled: enabled ? '1' : '0'})
|
// The array this row was rendered from, so the write lands in the list that was clicked. A
|
||||||
|
// script may sit in several with different arguments, and without this the endpoint acts on
|
||||||
|
// whichever one master.conf declares first.
|
||||||
|
vvPost('/plugins/varaverk/api/conf_toggle.php',
|
||||||
|
{id, enabled: enabled ? '1' : '0', array: child.dataset.confArray || ''})
|
||||||
.then(d => { if (d.ok) vvFlashSaved(child); });
|
.then(d => { if (d.ok) vvFlashSaved(child); });
|
||||||
} else {
|
} else {
|
||||||
const cron = child.querySelector('input.vv-cron')?.value.trim() ?? '';
|
const cron = child.querySelector('input.vv-cron')?.value.trim() ?? '';
|
||||||
|
|||||||
Reference in New Issue
Block a user