Add lnms commands to get and set config settings (#10534)

* add lnms commands to get and set config settings
lnms config:get and lnms config:set
Note: you cannot override settings in config.php

* Update to check setting exists and value validation rules.
This commit is contained in:
Tony Murray
2019-10-17 17:22:43 +00:00
committed by GitHub
parent 6c88436dce
commit 31dad0aaa7
8 changed files with 195 additions and 3 deletions

View File

@ -297,6 +297,23 @@ class Config
}
}
/**
* Forget a key and all it's descendants from persistent storage.
* This will effectively set it back to default.
*
* @param string $key
* @return int|false
*/
public static function erase($key)
{
self::forget($key);
try {
return \App\Models\Config::withChildren($key)->delete();
} catch (\Exception $e) {
return false;
}
}
/**
* Check if a setting is set
*

View File

@ -70,11 +70,13 @@ class DynamicConfigItem implements \ArrayAccess
} elseif ($this->type == 'boolean') {
return filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null;
} elseif ($this->type == 'integer') {
return filter_var($value, FILTER_VALIDATE_INT) || $value === "0" || $value === 0;
return (!is_bool($value) && filter_var($value, FILTER_VALIDATE_INT)) || $value === "0" || $value === 0;
} elseif ($this->type == 'select') {
return in_array($value, array_keys($this->options));
} elseif ($this->type == 'email') {
return filter_var($value, FILTER_VALIDATE_EMAIL);
} elseif ($this->type == 'array') {
return is_array($value); // this should probably have more complex validation via validator rules
} elseif (in_array($this->type, ['text', 'password'])) {
return true;
}
@ -185,7 +187,7 @@ class DynamicConfigItem implements \ArrayAccess
{
return $this->validate
? implode(" \n", $this->buildValidator($value)->messages()->get('value'))
: __('settings.validate.' . $this->type, ['id' => $this->name, 'value' => is_array($value) ? json_encode($value) : $value]);
: __('settings.validate.' . $this->type, ['id' => $this->name, 'value' => json_encode($value)]);
}
// ArrayAccess functions

View File

@ -0,0 +1,54 @@
<?php
namespace App\Console\Commands;
use App\Console\LnmsCommand;
use LibreNMS\Config;
use Symfony\Component\Console\Input\InputArgument;
class GetConfigCommand extends LnmsCommand
{
protected $name = 'config:get';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->addArgument('setting', InputArgument::OPTIONAL);
$this->addOption('json');
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$setting = $this->argument('setting');
if ($this->option('json')) {
$this->line($setting ? json_encode(Config::get($setting)) : Config::toJson());
return 0;
}
if (!$setting) {
throw new \RuntimeException('Not enough arguments (missing: "setting").');
}
if (Config::has($setting)) {
$output = Config::get($setting);
if (!is_string($output)) {
$output = var_export($output, 1);
}
$this->line($output);
return 0;
}
return 1;
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace App\Console\Commands;
use App\Console\LnmsCommand;
use LibreNMS\Config;
use LibreNMS\DB\Eloquent;
use LibreNMS\Util\DynamicConfig;
use Symfony\Component\Console\Input\InputArgument;
class SetConfigCommand extends LnmsCommand
{
protected $name = 'config:set';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->addArgument('setting', InputArgument::REQUIRED);
$this->addArgument('value', InputArgument::OPTIONAL);
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle(DynamicConfig $definition)
{
$setting = $this->argument('setting');
$value = $this->argument('value');
if (!$definition->isValidSetting($setting)) {
$this->error(__('This is not a valid setting. Please check your spelling'));
return 2;
}
if (!Eloquent::isConnected()) {
$this->error(__('Database is not connected'));
return 1;
}
if (!$value) {
if ($this->confirm(__('Reset :setting to the default?', ['setting' => $setting]))) {
Config::erase($setting);
return 0;
}
return 3;
}
$value = $this->juggleType($value);
$configItem = $definition->get($setting);
if (!$configItem->checkValue($value)) {
$this->error($configItem->getValidationMessage($value));
return 2;
}
if (Config::persist($setting, $value)) {
return 0;
}
$this->error(__('Failed to set :setting', ['setting' => $setting]));
return 1;
}
/**
* Convert the string input into the appropriate PHP native type
*
* @param $value
* @return mixed
*/
private function juggleType($value)
{
$json = json_decode($value, true);
return json_last_error() ? $value : $json;
}
}

View File

@ -34,6 +34,17 @@ abstract class LnmsCommand extends Command
{
protected $developer = false;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->setDescription(__('commands.' . $this->getName() . '.description'));
}
public function isHidden()
{
return $this->hidden || ($this->developer && $this->getLaravel()->environment() !== 'production');

View File

@ -69,7 +69,7 @@ class SettingsController extends Controller
return $this->jsonResponse($id, ":id is not a valid setting", null, 400);
}
$dbConfig = \App\Models\Config::where('config_name', 'like', "$id%")->get();
$dbConfig = \App\Models\Config::withChildren($id)->get();
if ($dbConfig->isEmpty()) {
return $this->jsonResponse($id, ":id is not set", $config->get($id)->default, 400);
}

View File

@ -38,6 +38,8 @@ class Config extends BaseModel
'config_default' => 'array'
];
// ---- Accessors/Mutators ----
public function getConfigValueAttribute($value)
{
return json_decode($value);
@ -47,4 +49,12 @@ class Config extends BaseModel
{
$this->attributes['config_value'] = json_encode($value, JSON_UNESCAPED_SLASHES);
}
// ---- Query Scopes ----
public function scopeWithChildren($query, $name)
{
return $query->where('config_name', $name)
->orWhere('config_name', 'like', "$name.%");
}
}

View File

@ -1,6 +1,22 @@
<?php
return [
'config:get' => [
'description' => 'Get configuration value',
'arguments' => [
'setting' => 'setting to get value of in dot notation (example: snmp.community.0)',
],
'options' => [
'json' => 'Output setting or entire config as json',
],
],
'config:set' => [
'description' => 'Set configuration value (or unset)',
'arguments' => [
'setting' => 'setting to set in dot notation (example: snmp.community.0)',
'value' => 'value to set, unset setting if this is omitted',
],
],
'user:add' => [
'description' => 'Add a local user, you can only log in with this user if auth is set to mysql',
'arguments' => [