diff options
Diffstat (limited to '')
-rw-r--r-- | library/Icingadb/Command/Transport/CommandTransport.php | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/library/Icingadb/Command/Transport/CommandTransport.php b/library/Icingadb/Command/Transport/CommandTransport.php new file mode 100644 index 0000000..ea125bc --- /dev/null +++ b/library/Icingadb/Command/Transport/CommandTransport.php @@ -0,0 +1,130 @@ +<?php + +/* Icinga DB Web | (c) 2021 Icinga GmbH | GPLv2 */ + +namespace Icinga\Module\Icingadb\Command\Transport; + +use Exception; +use Icinga\Application\Config; +use Icinga\Application\Logger; +use Icinga\Data\ConfigObject; +use Icinga\Exception\ConfigurationError; +use Icinga\Module\Icingadb\Command\IcingaCommand; + +/** + * Command transport + */ +class CommandTransport implements CommandTransportInterface +{ + /** + * Transport configuration + * + * @var Config + */ + protected static $config; + + /** + * Get transport configuration + * + * @return Config + * + * @throws ConfigurationError + */ + public static function getConfig(): Config + { + if (static::$config === null) { + $config = Config::module('icingadb', 'commandtransports'); + if ($config->isEmpty()) { + throw new ConfigurationError( + t('No command transports have been configured in "%s".'), + $config->getConfigFile() + ); + } + + static::$config = $config; + } + + return static::$config; + } + + /** + * Create a transport from config + * + * @param ConfigObject $config + * + * @return ApiCommandTransport + * + * @throws ConfigurationError + */ + public static function createTransport(ConfigObject $config): ApiCommandTransport + { + $config = clone $config; + switch (strtolower($config->transport)) { + case ApiCommandTransport::TRANSPORT: + $transport = new ApiCommandTransport(); + break; + default: + throw new ConfigurationError( + t('Cannot create command transport "%s". Invalid transport defined in "%s". Use one of: %s.'), + $config->transport, + static::getConfig()->getConfigFile(), + join(', ', [ApiCommandTransport::TRANSPORT]) + ); + } + + unset($config->transport); + foreach ($config as $key => $value) { + $method = 'set' . ucfirst($key); + if (! method_exists($transport, $method)) { + // Ignore settings from config that don't have a setter on the transport instead of throwing an + // exception here because the transport should throw an exception if it's not fully set up + // when being about to send a command + continue; + } + + $transport->$method($value); + } + + return $transport; + } + + /** + * Send the given command over an appropriate Icinga command transport + * + * This will try one configured transport after another until the command has been successfully sent. + * + * @param IcingaCommand $command The command to send + * @param int|null $now Timestamp of the command or null for now + * + * @throws CommandTransportException If sending the Icinga command failed + * + * @return mixed + */ + public function send(IcingaCommand $command, int $now = null) + { + $errors = []; + + foreach (static::getConfig() as $name => $transportConfig) { + $transport = static::createTransport($transportConfig); + + try { + $result = $transport->send($command, $now); + } catch (CommandTransportException $e) { + Logger::error($e); + $errors[] = sprintf('%s: %s.', $name, rtrim($e->getMessage(), '.')); + continue; // Try the next transport + } + + return $result; // The command was successfully sent + } + + if (! empty($errors)) { + throw new CommandTransportException(implode("\n", $errors)); + } + + throw new CommandTransportException(t( + 'Failed to send external Icinga command. No transport has been configured' + . ' for this instance. Please contact your Icinga Web administrator.' + )); + } +} |