Files
Netbox-Store/store/bin/console
T
MrBlake f36d6be511
CI / php-store (push) Waiting to run
CI / python-components (push) Waiting to run
feat: add NetBox plugin store
2026-08-24 20:51:25 +02:00

92 lines
3.3 KiB
PHP

#!/usr/bin/env php
<?php
declare(strict_types=1);
use NetBoxStore\Config;
use NetBoxStore\Database\RepositoryFactory;
use NetBoxStore\Security\Auth;
use NetBoxStore\Security\HttpClient;
use NetBoxStore\Security\SsrfGuard;
use NetBoxStore\Sync\SyncService;
$root = dirname(__DIR__);
require $root . '/vendor/autoload.php';
$command = $argv[1] ?? '';
if ($command === 'hash-password') {
try {
$password = $argv[2] ?? getenv('STORE_ADMIN_PASSWORD_TO_HASH') ?: '';
if ($password === '') {
throw new RuntimeException("Usage: php bin/console hash-password 'a-long-random-password'");
}
fwrite(STDOUT, Auth::passwordHash($password) . PHP_EOL);
exit(0);
} catch (Throwable $exception) {
fwrite(STDERR, $exception->getMessage() . PHP_EOL);
exit(1);
}
}
if (!in_array($command, ['sync', 'bootstrap'], true)) {
fwrite(STDERR, "Usage: php bin/console <hash-password|bootstrap|sync> [--watch] [--source=slug] [--interval=900] [--fail-fast]" . PHP_EOL);
exit(1);
}
try {
$config = Config::load($root);
$repository = RepositoryFactory::create($config);
$repository->initialize();
$guard = new SsrfGuard($config);
$http = new HttpClient($config, $guard);
$service = new SyncService($repository, $config, $http, $guard);
if (!in_array('--no-bootstrap', $argv, true)) {
$bootstrapped = $service->ensureDefaultSource();
if ($bootstrapped['created']) {
fwrite(STDOUT, 'Default source created: ' . $bootstrapped['source']['slug'] . PHP_EOL);
}
}
if ($command === 'bootstrap') {
exit(0);
}
$watch = in_array('--watch', $argv, true);
$failFast = in_array('--fail-fast', $argv, true);
$sources = [];
$interval = $config->scheduler['interval'];
foreach ($argv as $argument) {
if (str_starts_with($argument, '--source=')) {
$sources[] = substr($argument, 9);
} elseif (str_starts_with($argument, '--interval=')) {
$interval = max(30, min(604_800, (int) substr($argument, 11)));
}
}
$stopped = false;
if (function_exists('pcntl_async_signals')) {
pcntl_async_signals(true);
pcntl_signal(SIGINT, static function () use (&$stopped): void { $stopped = true; });
pcntl_signal(SIGTERM, static function () use (&$stopped): void { $stopped = true; });
}
do {
try {
$runs = $service->syncAll($sources === [] ? null : $sources, $failFast, $watch ? 'scheduled' : 'command');
fwrite(STDOUT, json_encode($runs, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR) . PHP_EOL);
if (!$watch && array_filter($runs, static fn (array $run): bool => $run['status'] === 'failed')) {
exit(1);
}
} catch (Throwable $exception) {
fwrite(STDERR, 'Sync failed: ' . $exception->getMessage() . PHP_EOL);
if (!$watch) {
exit(1);
}
}
if ($watch && !$stopped) {
for ($second = 0; $second < $interval && !$stopped; $second++) {
sleep(1);
}
}
} while ($watch && !$stopped);
exit(0);
} catch (Throwable $exception) {
fwrite(STDERR, $exception->getMessage() . PHP_EOL);
exit(1);
}