version and git helper improvements (#14412)

* Fix up version and git helpers
Improve method names
Move all git calls into the git helper
Allow runtime and external cache of results where appropriate
Consolidate version headers for discovery, poller, and validate

* Style fixes

* improve consistency in git calls

* fix style

* don't send name inconsistently

* Improve database versions

* No need to cache Version it is not used more than once currently.
This commit is contained in:
Tony Murray 2022-10-02 00:41:56 -05:00 committed by GitHub
parent 964a67289a
commit e4451714e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 441 additions and 337 deletions

View File

@ -167,7 +167,7 @@ class Schema
$update_cache = true;
$cache = [];
$cache_file = Config::get('install_dir') . "/cache/{$base}_relationships.cache";
$db_version = Version::get()->database();
$db_version = Version::get()->databaseMigrationCount();
if (is_file($cache_file)) {
$cache = unserialize(file_get_contents($cache_file));

View File

@ -25,6 +25,7 @@ use LibreNMS\DB\Eloquent;
use LibreNMS\Enum\AlertState;
use LibreNMS\Util\Number;
use LibreNMS\Util\Time;
use LibreNMS\Util\Version;
use Permissions;
class IRCBot
@ -781,11 +782,9 @@ class IRCBot
private function _version($params)
{
$versions = version_info();
$schema_version = $versions['db_schema'];
$version = $versions['local_ver'];
$version = Version::get();
$msg = $this->config['project_name'] . ', Version: ' . $version . ', DB schema: ' . $schema_version . ', PHP: ' . PHP_VERSION;
$msg = $this->config['project_name'] . ', Version: ' . $version->name() . ', DB schema: ' . $version->databaseMigrationCount() . ', PHP: ' . PHP_VERSION;
return $this->respond($msg);
}

View File

@ -40,9 +40,9 @@ use LibreNMS\Polling\ConnectivityHelper;
use LibreNMS\RRD\RrdDefinition;
use LibreNMS\Util\Debug;
use LibreNMS\Util\Dns;
use LibreNMS\Util\Git;
use LibreNMS\Util\Module;
use LibreNMS\Util\StringHelpers;
use LibreNMS\Util\Version;
use Psr\Log\LoggerInterface;
use Throwable;
@ -362,27 +362,7 @@ EOH, $this->device->hostname, $group ? " ($group)" : '', $this->device->device_i
private function printHeader(): void
{
if (Debug::isEnabled() || Debug::isVerbose()) {
$version = \LibreNMS\Util\Version::get();
$this->logger->info(sprintf(<<<'EOH'
===================================
Version info:
Commit SHA: %s
Commit Date: %s
DB Schema: %s
PHP: %s
Database: %s
RRDTool: %s
SNMP: %s
==================================
EOH,
Git::localCommit(),
Git::localDate(),
vsprintf('%s (%s)', $version->database()),
phpversion(),
$version->databaseServer(),
$version->rrdtool(),
$version->netSnmp()
));
$this->logger->info(Version::get()->header());
}
}
}

View File

@ -0,0 +1,55 @@
<?php
/**
* RuntimeClassCache.php
*
* Adds the ability to cache the output of functions either on the instance
* or in the global cache. Set $runtimeCacheExternalTTL to enable global cache.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2022 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace LibreNMS\Traits;
use Illuminate\Support\Facades\Cache;
use LibreNMS\Util\Laravel;
trait RuntimeClassCache
{
/** @var array */
private $runtimeCache = [];
/** @var int Setting this installs the data in the external cache to be shared across instances */
protected $runtimeCacheExternalTTL = 0;
/**
* We want these each runtime, so don't use the global cache
*
* @return mixed
*/
protected function cacheGet(string $name, callable $actual)
{
if (! array_key_exists($name, $this->runtimeCache)) {
$this->runtimeCache[$name] = $this->runtimeCacheExternalTTL && Laravel::isBooted()
? Cache::remember('runtimeCache' . __CLASS__ . $name, $this->runtimeCacheExternalTTL, $actual)
: $actual();
}
return $this->runtimeCache[$name];
}
}

View File

@ -25,74 +25,210 @@
namespace LibreNMS\Util;
use Carbon\Carbon;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Str;
use LibreNMS\Config;
use LibreNMS\Traits\RuntimeClassCache;
use Symfony\Component\Process\Process;
class Git
{
public static function repoPresent(): bool
{
$install_dir = Config::get('install_dir', realpath(__DIR__ . '/../..'));
use RuntimeClassCache;
return file_exists("$install_dir/.git");
/** @var string */
private $install_dir;
public function __construct(int $cache = 0)
{
$this->runtimeCacheExternalTTL = $cache;
$this->install_dir = Config::get('install_dir', realpath(__DIR__ . '/../..'));
}
public static function binaryExists(): bool
public static function make(int $cache = 0): Git
{
exec('git > /dev/null 2>&1', $response, $exit_code);
try {
$git = app()->make('git'); // get the singleton
$git->runtimeCacheExternalTTL = $cache;
return $exit_code === 1;
return $git;
} catch (BindingResolutionException $e) {
return new static($cache); // no container, just return a regular instance
}
}
public static function localCommit(): string
public function isAvailable(): bool
{
return rtrim(exec("git show --pretty='%H' -s HEAD"));
return $this->cacheGet('isAvailable', function () {
return $this->repoPresent() && $this->binaryExists();
});
}
public static function localDate(): Carbon
public function repoPresent(): bool
{
return \Date::createFromTimestamp(exec("git show --pretty='%ct' -s HEAD"));
return $this->cacheGet('repoPresent', function () {
return file_exists("$this->install_dir/.git");
});
}
public static function unchanged(): bool
public function binaryExists(): bool
{
$process = new Process(['git', 'diff-index', '--quiet', 'HEAD']);
$process->disableOutput();
$process->run();
return $this->cacheGet('binaryExists', function () {
return $this->run('help', [])->isSuccessful();
});
}
return $process->getExitCode() === 0;
public function tag(): string
{
return $this->cacheGet('tag', function () {
return $this->isAvailable()
? rtrim($this->run('describe', ['--tags'])->getOutput())
: '';
});
}
public function shortTag(): string
{
return $this->cacheGet('shortTag', function () {
return $this->isAvailable()
? rtrim($this->run('describe', ['--tags', '--abbrev=0'])->getOutput())
: '';
});
}
/**
* Returns the commit hash of the local HEAD commit
*/
public function commitHash(): string
{
return $this->headCommit()[0] ?? '';
}
/**
* Get the date of the local HEAD commit
*/
public function commitDate(): string
{
return $this->headCommit()[1] ?? '';
}
/**
* Get the current branch
*/
public function branch(): string
{
return $this->cacheGet('branch', function () {
return $this->isAvailable()
? rtrim($this->run('rev-parse', ['--abbrev-ref', 'HEAD'])->getOutput())
: '';
});
}
/**
* Detect if there are local uncommitted changes.
*/
public function hasChanges(): bool
{
return $this->cacheGet('hasChanges', function () {
return $this->isAvailable() && ! $this->run('diff-index', ['--quiet', 'HEAD'])->isSuccessful();
});
}
/**
* Note: It assumes origin/master points to github.com/librenms/librenms for this to work.
*/
public static function officalCommit(?string $hash = null, string $remote = 'origin/master'): bool
public function isOfficialCommit(): bool
{
if ($hash === null) {
$process = new Process(['git', 'rev-parse', 'HEAD']);
$process->run();
$hash = trim($process->getOutput());
}
$process = new Process(['git', 'branch', '--remotes', '--contains', $hash, $remote]);
$process->run();
if ($process->isSuccessful()) {
if (trim($process->getOutput()) == $remote) {
return true;
return $this->cacheGet('isOfficialCommit', function () {
if (! $this->isAvailable()) {
return false;
}
}
return false;
$process = $this->run('branch', ['--remotes', '--contains', $this->commitHash(), 'origin/master']);
return $process->isSuccessful() && trim($process->getOutput()) == 'origin/master';
});
}
public static function remoteUrl(string $remote = 'origin'): string
/**
* Get the url of the origin remote
*/
public function remoteUrl(): string
{
$process = new Process(['git', 'ls-remote', '--get-url', $remote]);
$process->run();
return $this->cacheGet('remoteUrl', function () {
return $this->isAvailable()
? rtrim($this->run('ls-remote', ['--get-url', 'origin'])->getOutput())
: '';
});
}
return trim($process->getOutput());
public function message(): string
{
return $this->cacheGet('remoteUrl', function () {
return $this->isAvailable()
? rtrim($this->run('log', ['--pretty=format:%s', '-n', '1'])->getOutput())
: '';
});
}
public function log(int $lines = 10): string
{
return $this->cacheGet('changelog' . $lines, function () use ($lines) {
return $this->isAvailable()
? rtrim($this->run('log', ['-' . $lines])->getOutput())
: '';
});
}
/**
* Fetches the remote commit hash from the github api if on the daily release channel
*/
public function remoteHash(): string
{
return $this->remoteCommit()['sha'] ?? '';
}
/**
* Fetches the remote commit from the github api if on the daily release channel
*/
private function remoteCommit(): array
{
return $this->cacheGet('remoteCommit', function () {
if ($this->isAvailable()) {
try {
return (array) \Http::withOptions(['proxy' => Proxy::forGuzzle()])->get(Config::get('github_api') . 'commits/master')->json();
} catch (ConnectionException $e) {
}
}
return [];
});
}
private function headCommit(): array
{
return $this->cacheGet('headCommit', function () {
if (! $this->isAvailable()) {
return [];
}
$version_process = $this->run('show', ['--quiet', '--pretty=%H|%ct']);
// failed due to permissions issue
if ($version_process->getExitCode() == 128 && Str::startsWith($version_process->getErrorOutput(), 'fatal: unsafe repository')) {
$this->run('config', ['--global', '--add', 'safe.directory', $this->install_dir]); // try to fix
$version_process = $this->run('show', ['--quiet', '--pretty=%H|%ct']); // and try again
}
return explode('|', rtrim($version_process->getOutput()));
});
}
private function run(string $command, array $options): Process
{
$version_process = new Process(array_merge(['git', $command], $options), $this->install_dir);
$version_process->run();
return $version_process;
}
}

View File

@ -26,29 +26,27 @@
namespace LibreNMS\Util;
use DB;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use LibreNMS\Config;
use LibreNMS\DB\Eloquent;
use Symfony\Component\Process\Process;
class Version
{
// Update this on release
/** @var string Update this on release */
public const VERSION = '22.9.0';
/** @var array */
protected $cache = [];
/** @var Git convenience instance */
public $git;
public function __construct()
{
$this->git = Git::make();
}
public static function get(): Version
{
try {
return app()->make('version');
} catch (BindingResolutionException $e) {
return new static; // no container, just return a fresh instance
}
return new static;
}
public function release(): string
@ -56,90 +54,14 @@ class Version
return Config::get('update_channel') == 'master' ? 'master' : self::VERSION;
}
public function local(): string
public function date(string $format = 'c'): string
{
return $this->cacheGet('local_version', function () {
if ($this->isGitInstall()) {
$version = rtrim(shell_exec('git describe --tags 2>/dev/null'));
if ($version) {
return $version;
}
}
return self::VERSION;
});
return date($format, $this->git->commitDate() ?: filemtime(__FILE__)); // approximate date for non-git installs
}
public function isGitInstall(): bool
public function name(): string
{
return $this->cacheGet('install_type', function () {
return (Git::repoPresent() && Git::binaryExists()) ? 'git' : 'other';
}) == 'git';
}
/**
* Compiles local commit data
*
* @return array with keys sha, date, and branch
*/
public function localCommit(): array
{
return [
'sha' => $this->localCommitSha(),
'date' => $this->localDate(),
'branch' => $this->localBranch(),
];
}
public function localCommitSha(): string
{
return $this->cacheGet('local_commit_sha', function () {
if (! $this->isGitInstall()) {
return '';
}
return $this->localCommitData()[0] ?? '';
});
}
public function localDate(): string
{
return $this->cacheGet('local_commit_date', function () {
return $this->localCommitData()[1] ?? '';
});
}
public function localBranch(): string
{
return $this->cacheGet('local_branch', function () {
if (! $this->isGitInstall()) {
return '';
}
$branch_process = new Process(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], Config::get('install_dir'));
$branch_process->run();
return rtrim($branch_process->getOutput());
});
}
/**
* Fetches the remote commit from the github api if on the daily release channel
*
* @return array
*/
public function remoteCommit(): array
{
return json_decode($this->cacheGet('remote_commit', function () {
if ($this->isGitInstall()) {
try {
return \Http::withOptions(['proxy' => Proxy::forGuzzle()])->get(Config::get('github_api') . 'commits/master')->body();
} catch (ConnectionException $e) {
}
}
return '[]';
}), true);
return $this->git->tag() ?: self::VERSION;
}
public function databaseServer(): string
@ -160,68 +82,74 @@ class Version
}
}
public function database(): array
/**
* Get the database last migration and count as a string
*/
public function database(): string
{
if (Eloquent::isConnected()) {
try {
$query = Eloquent::DB()->table('migrations');
return [
'last' => $query->orderBy('id', 'desc')->value('migration'),
'total' => $query->count(),
];
} catch (\Exception $e) {
return ['last' => 'No Schema', 'total' => 0];
}
}
return ['last' => 'Not Connected', 'total' => 0];
return sprintf('%s (%s)', $this->lastDatabaseMigration(), $this->databaseMigrationCount());
}
public function gitChangelog(): string
/**
* Get the total number of migrations applied to the database
*/
public function databaseMigrationCount(): int
{
return $this->cacheGet('changelog', function () {
return $this->isGitInstall()
? rtrim(shell_exec('git log -10'))
: '';
});
try {
if (Eloquent::isConnected()) {
return Eloquent::DB()->table('migrations')->count();
}
} catch (\Exception $e) {
}
return 0;
}
/**
* Get the name of the last migration that was applied to the database
*/
public function lastDatabaseMigration(): string
{
if (! Eloquent::isConnected()) {
return 'Not Connected';
}
try {
return Eloquent::DB()->table('migrations')->orderBy('id', 'desc')->value('migration');
} catch (\Exception $e) {
return 'No Schema';
}
}
public function python(): string
{
return $this->cacheGet('python', function () {
$proc = new Process(['python3', '--version']);
$proc->run();
$proc = new Process(['python3', '--version']);
$proc->run();
if ($proc->getExitCode() !== 0) {
return '';
}
if ($proc->getExitCode() !== 0) {
return '';
}
return explode(' ', rtrim($proc->getOutput()), 2)[1] ?? '';
});
return explode(' ', rtrim($proc->getOutput()), 2)[1] ?? '';
}
public function rrdtool(): string
{
return $this->cacheGet('rrdtool', function () {
$process = new Process([Config::get('rrdtool', 'rrdtool'), '--version']);
$process->run();
preg_match('/^RRDtool ([\w.]+) /', $process->getOutput(), $matches);
$process = new Process([Config::get('rrdtool', 'rrdtool'), '--version']);
$process->run();
preg_match('/^RRDtool ([\w.]+) /', $process->getOutput(), $matches);
return str_replace('1.7.01.7.0', '1.7.0', $matches[1] ?? '');
});
return str_replace('1.7.01.7.0', '1.7.0', $matches[1] ?? '');
}
public function netSnmp(): string
{
return $this->cacheGet('net-snmp', function () {
$process = new Process([Config::get('snmpget', 'snmpget'), '-V']);
$process = new Process([Config::get('snmpget', 'snmpget'), '-V']);
$process->run();
preg_match('/[\w.]+$/', $process->getErrorOutput(), $matches);
$process->run();
preg_match('/[\w.]+$/', $process->getErrorOutput(), $matches);
return $matches[0] ?? '';
});
return $matches[0] ?? '';
}
/**
@ -229,61 +157,61 @@ class Version
*/
public function os(): string
{
return $this->cacheGet('os', function () {
$info = [];
$info = [];
// find release file
if (file_exists('/etc/os-release')) {
$info = @parse_ini_file('/etc/os-release');
} else {
foreach (glob('/etc/*-release') as $file) {
$content = file_get_contents($file);
// normal os release style
$info = @parse_ini_string($content);
if (! empty($info)) {
break;
}
// find release file
if (file_exists('/etc/os-release')) {
$info = @parse_ini_file('/etc/os-release');
} else {
foreach (glob('/etc/*-release') as $file) {
$content = file_get_contents($file);
// normal os release style
$info = @parse_ini_string($content);
if (! empty($info)) {
break;
}
// just a string of text
if (substr_count($content, PHP_EOL) <= 1) {
$info = ['NAME' => trim(str_replace('release ', '', $content))];
break;
}
// just a string of text
if (substr_count($content, PHP_EOL) <= 1) {
$info = ['NAME' => trim(str_replace('release ', '', $content))];
break;
}
}
}
$only = array_intersect_key($info, ['NAME' => true, 'VERSION_ID' => true]);
$only = array_intersect_key($info, ['NAME' => true, 'VERSION_ID' => true]);
return implode(' ', $only);
});
return implode(' ', $only);
}
/**
* We want these each runtime, so don't use the global cache
* Get a formatted header to print out to the user.
*/
private function cacheGet(string $name, callable $actual): string
public function header(): string
{
if (! array_key_exists($name, $this->cache)) {
$this->cache[$name] = $actual($name);
}
return sprintf(<<<'EOH'
===========================================
Component | Version
--------- | -------
LibreNMS | %s (%s)
DB Schema | %s (%s)
PHP | %s
Python | %s
Database | %s
RRDTool | %s
SNMP | %s
===========================================
return $this->cache[$name];
}
private function localCommitData(): array
{
return explode('|', $this->cacheGet('local_commit_data', function () {
$install_dir = Config::get('install_dir');
$version_process = new Process(['git', 'show', '--quiet', '--pretty=%H|%ct'], $install_dir);
$version_process->run();
// failed due to permissions issue
if ($version_process->getExitCode() == 128 && Str::startsWith($version_process->getErrorOutput(), 'fatal: unsafe repository')) {
(new Process(['git', 'config', '--global', '--add', 'safe.directory', $install_dir]))->run();
$version_process->run();
}
return rtrim($version_process->getOutput());
}));
EOH,
$this->name(),
$this->date(),
$this->lastDatabaseMigration(),
$this->databaseMigrationCount(),
phpversion(),
$this->python(),
$this->databaseServer(),
$this->rrdtool(),
$this->netSnmp()
);
}
}

View File

@ -47,7 +47,7 @@ class Dependencies extends BaseValidation
}
// if git is not installed, do not assume composer is either
if (! Git::repoPresent()) {
if (! Git::make()->repoPresent()) {
$validator->ok('Installed from package; no Composer required');
return;

View File

@ -32,7 +32,6 @@ use LibreNMS\ComposerHelper;
use LibreNMS\Config;
use LibreNMS\Util\EnvHelper;
use LibreNMS\Util\Git;
use LibreNMS\Util\Version;
use LibreNMS\ValidationResult;
use LibreNMS\Validator;
use Symfony\Component\Process\Process;
@ -47,14 +46,14 @@ class Updates extends BaseValidation
return;
}
if (! Git::repoPresent()) {
if (! Git::make()->repoPresent()) {
$validator->warn('Non-git install, updates are manual or from package');
return;
}
// if git is not available, we cannot do the other tests
if (! Git::binaryExists()) {
if (! Git::make()->binaryExists()) {
$validator->warn('Unable to locate git. This should probably be installed.');
return;
@ -62,10 +61,9 @@ class Updates extends BaseValidation
// check if users on master update channel are up to date
if (Config::get('update_channel') == 'master') {
$local_ver = Version::get()->localCommit();
$remote_ver = Version::get()->remoteCommit();
if ($local_ver['sha'] != ($remote_ver['sha'] ?? null)) {
if (empty($local_ver['date'])) {
$git = Git::make();
if ($git->commitHash() != $git->remoteHash()) {
if (! $git->commitDate()) {
$process = new Process(['git', 'show', '--quiet', '--pretty=%H|%ct'], base_path());
$process->run();
$error = rtrim($process->getErrorOutput());
@ -73,7 +71,7 @@ class Updates extends BaseValidation
$validator->fail('Failed to fetch version from local git: ' . $error);
} else {
try {
$commit_date = new DateTime('@' . $local_ver['date'], new DateTimeZone(date_default_timezone_get()));
$commit_date = new DateTime('@' . $git->commitDate(), new DateTimeZone(date_default_timezone_get()));
if ($commit_date->diff(new DateTime())->days > 0) {
$validator->warn(
'Your install is over 24 hours out of date, last update: ' . $commit_date->format('r'),
@ -86,13 +84,14 @@ class Updates extends BaseValidation
}
}
if ($local_ver['branch'] != 'master') {
if ($local_ver['branch'] == 'php53') {
$branch = $git->branch();
if ($branch != 'master') {
if ($branch == 'php53') {
$validator->warn(
'You are on the PHP 5.3 support branch, this will prevent automatic updates.',
'Update to PHP 5.6.4 or newer (PHP ' . Php::PHP_RECOMMENDED_VERSION . ' recommended) to continue to receive updates.'
);
} elseif ($local_ver['branch'] == 'php56') {
} elseif ($branch == 'php56') {
$validator->warn(
'You are on the PHP 5.6/7.0 support branch, this will prevent automatic updates.',
'Update to PHP ' . Php::PHP_MIN_VERSION . ' or newer (PHP ' . Php::PHP_RECOMMENDED_VERSION . ' recommended) to continue to receive updates.'

View File

@ -74,7 +74,7 @@ class User extends BaseValidation
}
// if no git, then we probably have different permissions by design
if (! Git::repoPresent()) {
if (! Git::make()->repoPresent()) {
return;
}

View File

@ -66,12 +66,12 @@ class AboutController extends Controller
'callback_status' => $callback_status,
'callback_uuid' => $callback_status ? Callback::get('uuid') : null,
'db_schema' => vsprintf('%s (%s)', $version->database()),
'git_log' => $version->gitChangelog(),
'git_date' => $version->localDate(),
'db_schema' => $version->database(),
'git_log' => $version->git->log(),
'git_date' => $version->date(),
'project_name' => Config::get('project_name'),
'version_local' => $version->local(),
'version_local' => $version->name(),
'version_database' => $version->databaseServer(),
'version_php' => phpversion(),
'version_laravel' => App::version(),

View File

@ -0,0 +1,51 @@
<?php
/**
* AddGitInformation.php
*
* Add git information to Flare report, but use a cache so we don't destroy servers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2022 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Logging\Reporting\Middleware;
use Facade\FlareClient\Report;
use LibreNMS\Util\Git;
class AddGitInformation
{
/**
* @param \Facade\FlareClient\Report $report
* @param callable $next next in the pipeline
* @return mixed
*/
public function handle(Report $report, $next)
{
$git = Git::make(180);
$report->group('git', [
'hash' => $git->commitHash(),
'message' => $git->message(),
'tag' => $git->shortTag(),
'remote' => $git->remoteUrl(),
]);
return $next($report);
}
}

View File

@ -43,7 +43,7 @@ class SetGroups
$version = Version::get();
$report->group('LibreNMS', [
'Git version' => $version->local(),
'Git version' => $version->name(),
'App version' => Version::VERSION,
]);

View File

@ -31,8 +31,8 @@ class AppServiceProvider extends ServiceProvider
$this->app->singleton('device-cache', function ($app) {
return new \LibreNMS\Cache\Device();
});
$this->app->singleton('version', function ($app) {
return new \LibreNMS\Util\Version();
$this->app->singleton('git', function ($app) {
return new \LibreNMS\Util\Git();
});
$this->app->bind(\App\Models\Device::class, function () {

View File

@ -25,6 +25,7 @@
namespace App\Providers;
use App\Logging\Reporting\Middleware\AddGitInformation;
use App\Logging\Reporting\Middleware\CleanContext;
use App\Logging\Reporting\Middleware\SetGroups;
use ErrorException;
@ -69,6 +70,9 @@ class ErrorReportingProvider extends \Facade\Ignition\IgnitionServiceProvider
return \LibreNMS\Util\Version::VERSION;
});
// add git information, but cache it unlike the upstream provider
Flare::registerMiddleware(AddGitInformation::class);
// Filter some extra fields for privacy
// Move to header middleware when switching to spatie/laravel-ignition
Flare::registerMiddleware(CleanContext::class);
@ -114,20 +118,21 @@ class ErrorReportingProvider extends \Facade\Ignition\IgnitionServiceProvider
}
// Check git
if (Git::repoPresent()) {
if (! Str::contains(Git::remoteUrl(), ['git@github.com:librenms/librenms.git', 'https://github.com/librenms/librenms.git'])) {
$git = Git::make(180);
if ($git->isAvailable()) {
if (! Str::contains($git->remoteUrl(), ['git@github.com:librenms/librenms.git', 'https://github.com/librenms/librenms.git'])) {
\Log::debug('Reporting disabled because LibreNMS is not from the official repository');
return false;
}
if (! Git::unchanged()) {
if ($git->hasChanges()) {
\Log::debug('Reporting disabled because LibreNMS is not from the official repository');
return false;
}
if (! Git::officalCommit()) {
if (! $git->isOfficialCommit()) {
\Log::debug('Reporting disabled due to local modifications');
return false;

View File

@ -34,14 +34,14 @@ return [
'reporting' => [
'anonymize_ips' => true,
'collect_git_information' => true,
'collect_git_information' => false,
'report_queries' => true,
'maximum_number_of_collected_queries' => 200,
'maximum_number_of_collected_queries' => 50,
'report_query_bindings' => true,
'report_view_data' => true,
'grouping_type' => null,
'report_logs' => false,
'maximum_number_of_collected_logs' => 200,
'maximum_number_of_collected_logs' => 50,
'censor_request_body_fields' => ['username', 'password', 'sysContact', 'community', 'authname', 'authpass', 'cryptopass'],
],

View File

@ -64,19 +64,7 @@ if (isset($options['i']) && $options['i'] && isset($options['n'])) {
}
if (Debug::set(isset($options['d']), false) || isset($options['v'])) {
$versions = version_info();
echo <<<EOH
===================================
Version info:
Commit SHA: {$versions['local_sha']}
Commit Date: {$versions['local_date']}
DB Schema: {$versions['db_schema']}
PHP: {$versions['php_ver']}
Database: {$versions['database_ver']}
RRDTool: {$versions['rrdtool_ver']}
SNMP: {$versions['netsnmp_ver']}
==================================
EOH;
echo \LibreNMS\Util\Version::get()->header();
echo "DEBUG!\n";
Debug::setVerbose(isset($options['v']));

View File

@ -532,31 +532,6 @@ function parse_location($location)
return false;
}//end parse_location()
/**
* Returns version info
*
* @param bool $remote fetch remote version info from github
* @return array
*/
function version_info($remote = false)
{
$version = \LibreNMS\Util\Version::get();
return [
'local_ver' => $version->local(),
'local_sha' => $version->localCommitSha(),
'local_date' => $version->localDate(),
'local_branch' => $version->localBranch(),
'github' => $remote ? $version->remoteCommit() : null,
'db_schema' => vsprintf('%s (%s)', $version->database()),
'php_ver' => phpversion(),
'python_ver' => $version->python(),
'database_ver' => $version->databaseServer(),
'rrdtool_ver' => $version->rrdtool(),
'netsnmp_ver' => $version->netSnmp(),
];
}//end version_info()
/**
* Convert a MySQL binary v4 (4-byte) or v6 (16-byte) IP address to a printable string.
*

View File

@ -2931,7 +2931,20 @@ function edit_service_for_host(Illuminate\Http\Request $request)
*/
function server_info()
{
$versions = version_info();
$version = \LibreNMS\Util\Version::get();
$versions = [
'local_ver' => $version->name(),
'local_sha' => $version->git->commitHash(),
'local_date' => $version->date(),
'local_branch' => $version->git->branch(),
'db_schema' => $version->database(),
'php_ver' => phpversion(),
'python_ver' => $version->python(),
'database_ver' => $version->databaseServer(),
'rrdtool_ver' => $version->rrdtool(),
'netsnmp_ver' => $version->netSnmp(),
];
return api_success([
$versions,

View File

@ -99,19 +99,7 @@ if (empty($where)) {
}
if (Debug::set(isset($options['d']), false) || isset($options['v'])) {
$versions = version_info();
echo <<<EOH
===================================
Version info:
Commit SHA: {$versions['local_sha']}
Commit Date: {$versions['local_date']}
DB Schema: {$versions['db_schema']}
PHP: {$versions['php_ver']}
Database: {$versions['database_ver']}
RRDTool: {$versions['rrdtool_ver']}
SNMP: {$versions['netsnmp_ver']}
==================================
EOH;
echo \LibreNMS\Util\Version::get()->header();
echo "DEBUG!\n";
if (isset($options['v'])) {

View File

@ -80,7 +80,7 @@ register_shutdown_function(function () {
spl_autoload_register(function ($class) {
@include str_replace('\\', '/', $class) . '.php';
});
print_header(version_info());
print_header();
}
});
@ -134,7 +134,7 @@ if (\LibreNMS\DB\Eloquent::isConnected()) {
}
$precheck_complete = true; // disable shutdown function
print_header(version_info());
print_header();
if (isset($options['g'])) {
$modules = explode(',', $options['g']);
@ -147,26 +147,13 @@ if (isset($options['g'])) {
// run checks
$validator->validate($modules, isset($options['s']) || ! empty($modules));
function print_header($versions)
function print_header()
{
$output = ob_get_clean();
@ob_end_clean();
echo <<< EOF
====================================
Component | Version
--------- | -------
LibreNMS | ${versions['local_ver']}
DB Schema | ${versions['db_schema']}
PHP | ${versions['php_ver']}
Python | ${versions['python_ver']}
Database | ${versions['database_ver']}
RRDTool | ${versions['rrdtool_ver']}
SNMP | ${versions['netsnmp_ver']}
====================================
$output
EOF;
echo \LibreNMS\Util\Version::get()->header() . PHP_EOL;
echo $output;
}
// output matches that of ValidationResult