diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php index d5d4d9cd..836d7002 100644 --- a/application/controllers/ConfigController.php +++ b/application/controllers/ConfigController.php @@ -23,6 +23,7 @@ use ipl\Sql\Connection; use ipl\Stdlib\Filter; use LogicException; +use Ramsey\Uuid\Uuid; use Throwable; class ConfigController extends Controller @@ -187,33 +188,30 @@ function (NotificationsConfigForm $form) use ($kconfig, $sourceForm) { public function prometheusAction() { - $db = Database::connection(); - $dbConfig = KConfig::on($db)->filter( - Filter::any( - Filter::equal('key', self::PROMETHEUS_URL), - Filter::equal('key', self::PROMETHEUS_USERNAME), - Filter::equal('key', self::PROMETHEUS_PASSWORD) - ) - ); - - $data = []; - - foreach ($dbConfig as $pair) { - $data[str_replace('.', '_', $pair->key)] = $pair->value; - } - $form = (new PrometheusConfigForm()) - ->populate($data) - ->on(PrometheusConfigForm::ON_SUCCESS, function ($form) use ($db, $dbConfig) { - if ($form->isLocked()) { + ->on(PrometheusConfigForm::ON_SUCCESS, function (PrometheusConfigForm $form) { + $clusterUuid = $form->getValue('cluster_uuid'); + if ($form->isLocked($clusterUuid)) { Notification::error($this->translate('Prometheus configuration is locked')); return; } try { + $db = Database::connection(); $db->exec("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"); $db->beginTransaction(); + $dbConfig = KConfig::on($db)->filter( + Filter::all( + Filter::equal('cluster_uuid', Uuid::fromString($clusterUuid)->getBytes()), + Filter::any( + Filter::equal('key', self::PROMETHEUS_URL), + Filter::equal('key', self::PROMETHEUS_USERNAME), + Filter::equal('key', self::PROMETHEUS_PASSWORD) + ) + ) + ); + $data = []; foreach ($dbConfig as $pair) { @@ -223,15 +221,23 @@ public function prometheusAction() if (isset($data[self::PROMETHEUS_URL]) && $data[self::PROMETHEUS_URL]['locked'] !== 'y') { $db->update( 'config', - ['value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_URL))], - [$db->quoteIdentifier('key') . ' = ?' => self::PROMETHEUS_URL] + [ + 'value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_URL)) + ], + [ + 'cluster_uuid = ?' => Uuid::fromString($clusterUuid)->getBytes(), + $db->quoteIdentifier('key') . ' = ?' => self::PROMETHEUS_URL, + ] ); } elseif (! isset($data[self::PROMETHEUS_URL])) { $db->insert( 'config', [ + 'cluster_uuid' => Uuid::fromString($clusterUuid)->getBytes(), $db->quoteIdentifier('key') => self::PROMETHEUS_URL, - 'value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_URL)) + 'value' => $form->getValue( + $this->fieldForForm(self::PROMETHEUS_URL) + ) ] ); } @@ -239,15 +245,23 @@ public function prometheusAction() if (isset($data[self::PROMETHEUS_USERNAME]) && $data[self::PROMETHEUS_USERNAME]['locked'] !== 'y') { $db->update( 'config', - ['value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_USERNAME))], - [$db->quoteIdentifier('key') . ' = ?' => self::PROMETHEUS_USERNAME] + [ + 'value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_USERNAME)) + ], + [ + 'cluster_uuid = ?' => Uuid::fromString($clusterUuid)->getBytes(), + $db->quoteIdentifier('key') . ' = ?' => self::PROMETHEUS_USERNAME + ] ); } elseif (! isset($data[self::PROMETHEUS_USERNAME])) { $db->insert( 'config', [ + 'cluster_uuid' => Uuid::fromString($clusterUuid)->getBytes(), $db->quoteIdentifier('key') => self::PROMETHEUS_USERNAME, - 'value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_USERNAME)) + 'value' => $form->getValue( + $this->fieldForForm(self::PROMETHEUS_USERNAME) + ) ] ); } @@ -255,23 +269,33 @@ public function prometheusAction() if (isset($data[self::PROMETHEUS_PASSWORD]) && $data[self::PROMETHEUS_PASSWORD]['locked'] !== 'y') { $db->update( 'config', - ['value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_PASSWORD))], - [$db->quoteIdentifier('key') . ' = ?' => self::PROMETHEUS_PASSWORD] + [ + 'value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_PASSWORD)) + ], + [ + 'cluster_uuid = ?' => Uuid::fromString($clusterUuid)->getBytes(), + $db->quoteIdentifier('key') . ' = ?' => self::PROMETHEUS_PASSWORD + ] ); } elseif (! isset($data[self::PROMETHEUS_PASSWORD])) { $db->insert( 'config', [ + 'cluster_uuid' => Uuid::fromString($clusterUuid)->getBytes(), $db->quoteIdentifier('key') => self::PROMETHEUS_PASSWORD, - 'value' => $form->getValue($this->fieldForForm(self::PROMETHEUS_PASSWORD)) + 'value' => $form->getValue( + $this->fieldForForm(self::PROMETHEUS_PASSWORD) + ) ] ); } $db->commitTransaction(); - } catch (Exception $_) { + } catch (Exception $e) { $db->rollBackTransaction(); - Notification::error($this->translate('Failed to store new configuration')); + Notification::error( + $this->translate('Failed to store new configuration') . ': ' . $e->getMessage() + ); return; } diff --git a/application/forms/PrometheusConfigForm.php b/application/forms/PrometheusConfigForm.php index 4b9c87bd..34b55490 100644 --- a/application/forms/PrometheusConfigForm.php +++ b/application/forms/PrometheusConfigForm.php @@ -6,17 +6,58 @@ use Icinga\Module\Kubernetes\Common\Database; use Icinga\Module\Kubernetes\Controllers\ConfigController; +use Icinga\Module\Kubernetes\Model\Cluster; use Icinga\Module\Kubernetes\Model\Config; +use Icinga\Module\Kubernetes\Web\ClusterForm; use ipl\Html\Attributes; use ipl\Html\Html; use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatForm; +use Ramsey\Uuid\Uuid; class PrometheusConfigForm extends CompatForm { protected function assemble(): void { - if ($this->isLocked()) { + $clusterUuid = $this->getPopulatedValue('cluster_uuid') ?? + (string) Uuid::fromBytes(Cluster::on(Database::connection())->orderBy('uuid')->first()->uuid); + + $this->addElement('hidden', 'old_cluster_uuid', ['value' => $clusterUuid]); + + if ($clusterUuid !== $this->getPopulatedValue('old_cluster_uuid', $clusterUuid)) { + $this->clearPopulatedValue('prometheus_url'); + } + + $dbConfig = Config::on(Database::connection())->filter( + Filter::all( + Filter::equal('cluster_uuid', Uuid::fromString($clusterUuid)->getBytes()), + Filter::any( + Filter::equal('key', ConfigController::PROMETHEUS_URL), + Filter::equal('key', ConfigController::PROMETHEUS_USERNAME), + Filter::equal('key', ConfigController::PROMETHEUS_PASSWORD) + ) + ) + ); + + $data = []; + + foreach ($dbConfig as $pair) { + $data[$pair->key] = ['value' => $pair->value, 'locked' => $pair->locked]; + } + + $this->addElement( + 'select', + 'cluster_uuid', + [ + 'required' => true, + 'class' => 'autosubmit', + 'label' => $this->translate('Cluster'), + 'options' => iterator_to_array(ClusterForm::yieldClusters()), + 'value' => $clusterUuid, + ], + ); + + if ($this->isLocked($clusterUuid)) { $this->addHtml( Html::tag('div', Attributes::create(['class' => 'control-group']), [ Html::tag( @@ -38,7 +79,8 @@ protected function assemble(): void [ 'label' => $this->translate('URL'), 'required' => true, - 'disabled' => $this->isLocked(), + 'value' => $data[ConfigController::PROMETHEUS_URL]['value'] ?? '', + 'disabled' => $this->isLocked($clusterUuid), ] ); @@ -47,7 +89,8 @@ protected function assemble(): void 'prometheus_username', [ 'label' => $this->translate('Username'), - 'disabled' => $this->isLocked(), + 'value' => $data[ConfigController::PROMETHEUS_USERNAME]['value'] ?? '', + 'disabled' => $this->isLocked($clusterUuid), ] ); @@ -56,7 +99,8 @@ protected function assemble(): void 'prometheus_password', [ 'label' => $this->translate('Password'), - 'disabled' => $this->isLocked(), + 'value' => $data[ConfigController::PROMETHEUS_PASSWORD]['value'] ?? '', + 'disabled' => $this->isLocked($clusterUuid), ] ); @@ -65,22 +109,22 @@ protected function assemble(): void 'submit', [ 'label' => $this->translate('Save Changes'), - 'disabled' => $this->isLocked() + 'disabled' => $this->isLocked($clusterUuid), ] ); } - public function isLocked(): bool + public function isLocked(string $clusterUuid): bool { - $config = Config::on(Database::connection()); - $config->filter(Filter::equal('key', ConfigController::PROMETHEUS_URL)); - - $temp = $config->first(); - - if (isset($config->first()->locked) && $config->first()->locked === 'y') { - return true; - } + $config = Config::on(Database::connection()) + ->filter( + Filter::all( + Filter::equal('cluster_uuid', Uuid::fromString($clusterUuid)->getBytes()), + Filter::equal('key', ConfigController::PROMETHEUS_URL), + ) + ) + ->first(); - return false; + return $config->locked ?? false; } } diff --git a/library/Kubernetes/Model/Config.php b/library/Kubernetes/Model/Config.php index 2006677c..766ce408 100644 --- a/library/Kubernetes/Model/Config.php +++ b/library/Kubernetes/Model/Config.php @@ -32,14 +32,15 @@ public function getTableName(): string return 'config'; } - public function getKeyName(): string + public function getKeyName(): array { - return 'key'; + return ['cluster_uuid', 'key']; } public function getColumns(): array { return [ + 'cluster_uuid', 'key', 'value', 'locked' diff --git a/library/Kubernetes/Web/ClusterForm.php b/library/Kubernetes/Web/ClusterForm.php index 513aebb2..9b53978c 100644 --- a/library/Kubernetes/Web/ClusterForm.php +++ b/library/Kubernetes/Web/ClusterForm.php @@ -14,7 +14,7 @@ class ClusterForm extends CompatForm { public const ALL_CLUSTERS = '-'; - protected function yieldClusters(): Generator + public static function yieldClusters(): Generator { $clusters = Cluster::on(Database::connection()) ->columns(['uuid', 'name']); @@ -37,7 +37,7 @@ protected function assemble(): void 'label' => $this->translate('Cluster'), 'options' => [ static::ALL_CLUSTERS => $this->translate('All clusters'), - ] + iterator_to_array($this->yieldClusters()), + ] + iterator_to_array(ClusterForm::yieldClusters()), ], ); }