summaryrefslogtreecommitdiffstats
path: root/application/clicommands
diff options
context:
space:
mode:
Diffstat (limited to 'application/clicommands')
-rw-r--r--application/clicommands/AutocompleteCommand.php120
-rw-r--r--application/clicommands/HelpCommand.php43
-rw-r--r--application/clicommands/ModuleCommand.php228
-rw-r--r--application/clicommands/VersionCommand.php55
-rw-r--r--application/clicommands/WebCommand.php101
5 files changed, 547 insertions, 0 deletions
diff --git a/application/clicommands/AutocompleteCommand.php b/application/clicommands/AutocompleteCommand.php
new file mode 100644
index 0000000..34e4005
--- /dev/null
+++ b/application/clicommands/AutocompleteCommand.php
@@ -0,0 +1,120 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Clicommands;
+
+use Icinga\Cli\Command;
+use Icinga\Cli\Loader;
+
+/**
+ * Autocomplete for modules, commands and actions
+ *
+ * The autocomplete command shows help for a given command, module and also for a
+ * given module's command or a specific command's action.
+ *
+ * Usage: icingacli autocomplete [<module>] [<command> [<action>]]
+ */
+class AutocompleteCommand extends Command
+{
+ protected $defaultActionName = 'complete';
+
+ protected function suggest($suggestions)
+ {
+ if ($suggestions) {
+ $key = array_search('autocomplete', $suggestions);
+ if ($key !== false) {
+ unset($suggestions[$key]);
+ }
+ echo implode("\n", $suggestions)
+ //. serialize($GLOBALS['argv'])
+ . "\n";
+ }
+ }
+
+ /**
+ * Show help for modules, commands and actions [default]
+ *
+ * The help command shows help for a given command, module and also for a
+ * given module's command or a specific command's action.
+ *
+ * Usage: icingacli autocomplete [<module>] [<command> [<action>]]
+ */
+ public function completeAction()
+ {
+ $module = null;
+ $command = null;
+ $action = null;
+
+ $loader = new Loader($this->app);
+ $params = $this->params;
+ $bare_params = $GLOBALS['argv'];
+ $cword = (int) $params->shift('autoindex');
+
+ $search_word = $bare_params[$cword];
+ if ($search_word === '--') {
+ // TODO: Unfinished, completion missing
+ return $this->suggest(array('--verbose', '--help', '--debug'));
+ }
+
+ $search = $params->shift();
+ if (!$search) {
+ return $this->suggest(
+ array_merge($loader->listCommands(), $loader->listModules())
+ );
+ }
+ $found = $loader->resolveName($search);
+ if ($found) {
+ // Do not return suggestions if we are already on the next word:
+ if ($bare_params[$cword] === $search) {
+ return $this->suggest(array($found));
+ }
+ } else {
+ return $this->suggest($loader->getLastSuggestions());
+ }
+
+ $obj = null;
+ if ($loader->hasCommand($found)) {
+ $command = $found;
+ $obj = $loader->getCommandInstance($command);
+ } elseif ($loader->hasModule($found)) {
+ $module = $found;
+ $search = $params->shift();
+ if (! $search) {
+ return $this->suggest(
+ $loader->listModuleCommands($module)
+ );
+ }
+ $command = $loader->resolveModuleCommandName($found, $search);
+ if ($command) {
+ // Do not return suggestions if we are already on the next word:
+ if ($bare_params[$cword] === $search) {
+ return $this->suggest(array($command));
+ }
+ $obj = $loader->getModuleCommandInstance(
+ $module,
+ $command
+ );
+ } else {
+ return $this->suggest($loader->getLastSuggestions());
+ }
+ }
+
+ if ($obj !== null) {
+ $search = $params->shift();
+ if (! $search) {
+ return $this->suggest($obj->listActions());
+ }
+ $action = $loader->resolveObjectActionName(
+ $obj,
+ $search
+ );
+ if ($action) {
+ if ($bare_params[$cword] === $search) {
+ return $this->suggest(array($action));
+ }
+ } else {
+ return $this->suggest($loader->getLastSuggestions());
+ }
+ }
+ }
+}
diff --git a/application/clicommands/HelpCommand.php b/application/clicommands/HelpCommand.php
new file mode 100644
index 0000000..a863eb4
--- /dev/null
+++ b/application/clicommands/HelpCommand.php
@@ -0,0 +1,43 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Clicommands;
+
+use Icinga\Cli\Command;
+use Icinga\Cli\Loader;
+use Icinga\Cli\Documentation;
+
+/**
+ * Help for modules, commands and actions
+ *
+ * The help command shows help for a given command, module and also for a
+ * given module's command or a specific command's action.
+ *
+ * Usage: icingacli help [<module>] [<command> [<action>]]
+ */
+class HelpCommand extends Command
+{
+ protected $defaultActionName = 'show';
+
+ /**
+ * Show help for modules, commands and actions [default]
+ *
+ * The help command shows help for a given command, module and also for a
+ * given module's command or a specific command's action.
+ *
+ * Usage: icingacli help [<module>] [<command> [<action>]]
+ */
+ public function showAction()
+ {
+ $module = null;
+ $command = null;
+ $action = null;
+ $loader = new Loader($this->app);
+ $loader->parseParams();
+ echo $this->docs()->usage(
+ $loader->getModuleName(),
+ $loader->getCommandName(),
+ $loader->getActionName()
+ );
+ }
+}
diff --git a/application/clicommands/ModuleCommand.php b/application/clicommands/ModuleCommand.php
new file mode 100644
index 0000000..fc42167
--- /dev/null
+++ b/application/clicommands/ModuleCommand.php
@@ -0,0 +1,228 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Clicommands;
+
+use Icinga\Application\Logger;
+use Icinga\Application\Modules\Manager;
+use Icinga\Cli\Command;
+
+/**
+ * List and handle modules
+ *
+ * The module command allows you to handle your IcingaWeb modules
+ *
+ * Usage: icingacli module [<action>] [<modulename>]
+ */
+class ModuleCommand extends Command
+{
+ /**
+ * @var Manager
+ */
+ protected $modules;
+
+ public function init()
+ {
+ $this->modules = $this->app->getModuleManager();
+ }
+
+ /**
+ * List all enabled modules
+ *
+ * If you are interested in all installed modules pass 'installed' (or
+ * even --installed) as a command parameter. If you enable --verbose even
+ * more details will be shown
+ *
+ * Usage: icingacli module list [installed] [--verbose]
+ */
+ public function listAction()
+ {
+ if ($type = $this->params->shift()) {
+ if (! in_array($type, array('enabled', 'installed'))) {
+ return $this->showUsage();
+ }
+ } else {
+ $type = 'enabled';
+ $this->params->shift('enabled');
+ if ($this->params->shift('installed')) {
+ $type = 'installed';
+ }
+ }
+
+ if ($this->hasRemainingParams()) {
+ return $this->showUsage();
+ }
+
+ if ($type === 'enabled') {
+ $modules = $this->modules->listEnabledModules();
+ } else {
+ $modules = $this->modules->listInstalledModules();
+ }
+ if (empty($modules)) {
+ echo "There are no $type modules\n";
+ return;
+ }
+ if ($this->isVerbose) {
+ printf("%-14s %-9s %-9s DIRECTORY\n", 'MODULE', 'VERSION', 'STATE');
+ } else {
+ printf("%-14s %-9s %-9s %s\n", 'MODULE', 'VERSION', 'STATE', 'DESCRIPTION');
+ }
+ foreach ($modules as $module) {
+ $mod = $this->modules->loadModule($module)->getModule($module);
+ if ($this->isVerbose) {
+ $dir = ' ' . $this->modules->getModuleDir($module);
+ } else {
+ $dir = $mod->getTitle();
+ }
+ printf(
+ "%-14s %-9s %-9s %s\n",
+ $module,
+ $mod->getVersion(),
+ ($type === 'enabled' || $this->modules->hasEnabled($module))
+ ? $this->modules->hasInstalled($module) ? 'enabled' : 'dangling'
+ : 'disabled',
+ $dir
+ );
+ }
+ echo "\n";
+ }
+
+ /**
+ * Enable a given module
+ *
+ * Usage: icingacli module enable <module-name>
+ */
+ public function enableAction()
+ {
+ if (! $module = $this->params->shift()) {
+ $module = $this->params->shift('module');
+ }
+
+ if (! $module || $this->hasRemainingParams()) {
+ return $this->showUsage();
+ }
+
+ $this->modules->enableModule($module, true);
+ }
+
+ /**
+ * Disable a given module
+ *
+ * Usage: icingacli module disable <module-name>
+ */
+ public function disableAction()
+ {
+ if (! $module = $this->params->shift()) {
+ $module = $this->params->shift('module');
+ }
+ if (! $module || $this->hasRemainingParams()) {
+ return $this->showUsage();
+ }
+
+ if ($this->modules->hasEnabled($module)) {
+ $this->modules->disableModule($module);
+ } else {
+ Logger::info('Module "%s" is already disabled', $module);
+ }
+ }
+
+ /**
+ * Show all restrictions provided by your modules
+ *
+ * Asks each enabled module for all available restriction names and
+ * descriptions and shows a quick overview
+ *
+ * Usage: icingacli module restrictions
+ */
+ public function restrictionsAction()
+ {
+ printf("%-14s %-16s %s\n", 'MODULE', 'RESTRICTION', 'DESCRIPTION');
+ foreach ($this->modules->listEnabledModules() as $moduleName) {
+ $module = $this->modules->loadModule($moduleName)->getModule($moduleName);
+ foreach ($module->getProvidedRestrictions() as $restriction) {
+ printf(
+ "%-14s %-16s %s\n",
+ $moduleName,
+ $restriction->name,
+ $restriction->description
+ );
+ }
+ }
+ }
+
+ /**
+ * Show all permissions provided by your modules
+ *
+ * Asks each enabled module for it's available permission names and
+ * descriptions and shows a quick overview
+ *
+ * Usage: icingacli module permissions
+ */
+ public function permissionsAction()
+ {
+ printf("%-14s %-24s %s\n", 'MODULE', 'PERMISSION', 'DESCRIPTION');
+ foreach ($this->modules->listEnabledModules() as $moduleName) {
+ $module = $this->modules->loadModule($moduleName)->getModule($moduleName);
+ foreach ($module->getProvidedPermissions() as $restriction) {
+ printf(
+ "%-14s %-24s %s\n",
+ $moduleName,
+ $restriction->name,
+ $restriction->description
+ );
+ }
+ }
+ }
+
+ /**
+ * Search for a given module
+ *
+ * Does a lookup against your configured IcingaWeb app stores and tries to
+ * find modules matching your search string
+ *
+ * Usage: icingacli module search <search-string>
+ */
+ public function searchAction()
+ {
+ $this->fail("Not implemented yet");
+ }
+
+ /**
+ * Install a given module
+ *
+ * Downloads a given module or installes a module from a given archive
+ *
+ * Usage: icingacli module install <module-name>
+ * icingacli module install </path/to/archive.tar.gz>
+ */
+ public function installAction()
+ {
+ $this->fail("Not implemented yet");
+ }
+
+ /**
+ * Remove a given module
+ *
+ * Removes the given module from your disk. Module configuration will be
+ * preserved
+ *
+ * Usage: icingacli module remove <module-name>
+ */
+ public function removeAction()
+ {
+ $this->fail("Not implemented yet");
+ }
+
+ /**
+ * Purge a given module
+ *
+ * Removes the given module from your disk. Also wipes configuration files
+ * and other data stored and/or generated by this module
+ *
+ * Usage: icingacli module remove <module-name>
+ */
+ public function purgeAction()
+ {
+ $this->fail("Not implemented yet");
+ }
+}
diff --git a/application/clicommands/VersionCommand.php b/application/clicommands/VersionCommand.php
new file mode 100644
index 0000000..9bdd443
--- /dev/null
+++ b/application/clicommands/VersionCommand.php
@@ -0,0 +1,55 @@
+<?php
+/* Icinga Web 2 | (c) 2019 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Clicommands;
+
+use Icinga\Application\Version;
+use Icinga\Application\Icinga;
+use Icinga\Cli\Loader;
+use Icinga\Cli\Command;
+
+/**
+ * Shows version of Icinga Web 2, loaded modules and PHP
+ *
+ * The version command shows version numbers for Icinga Web 2, loaded modules and PHP.
+ *
+ * Usage: icingacli --version
+ */
+class VersionCommand extends Command
+{
+ protected $defaultActionName = 'show';
+
+ /**
+ * Shows version of Icinga Web 2, loaded modules and PHP
+ *
+ * The version command shows version numbers for Icinga Web 2, loaded modules and PHP.
+ *
+ * Usage: icingacli --version
+ */
+ public function showAction()
+ {
+ $getVersion = Version::get();
+ printf("%-12s %-9s \n", 'Icinga Web 2', $getVersion['appVersion']);
+
+ if (isset($getVersion['gitCommitID'])) {
+ printf("%-12s %-9s \n", 'Git Commit', $getVersion['gitCommitID']);
+ }
+
+ printf("%-12s %-9s \n", 'PHP Version', PHP_VERSION);
+
+ $modules = Icinga::app()->getModuleManager()->loadEnabledModules()->getLoadedModules();
+
+ $maxLength = 0;
+ foreach ($modules as $module) {
+ $length = strlen($module->getName());
+ if ($length > $maxLength) {
+ $maxLength = $length;
+ }
+ }
+
+ printf("%-{$maxLength}s %-9s \n", 'MODULE', 'VERSION');
+ foreach ($modules as $module) {
+ printf("%-{$maxLength}s %-9s \n", $module->getName(), $module->getVersion());
+ }
+ }
+}
diff --git a/application/clicommands/WebCommand.php b/application/clicommands/WebCommand.php
new file mode 100644
index 0000000..67d50a3
--- /dev/null
+++ b/application/clicommands/WebCommand.php
@@ -0,0 +1,101 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Clicommands;
+
+use Icinga\Application\Icinga;
+use Icinga\Cli\Command;
+use Icinga\Exception\IcingaException;
+
+class WebCommand extends Command
+{
+ /**
+ * Serve Icinga Web 2 with PHP's built-in web server
+ *
+ * USAGE
+ *
+ * icingacli web serve [options] [<document-root>]
+ *
+ * OPTIONS
+ *
+ * --daemonize Run in background
+ * --port=<port> The port to listen on
+ * --listen=<host:port> The address to listen on
+ * <document-root> The document root directory of Icinga Web 2 (e.g. ./public)
+ *
+ * EXAMPLES
+ *
+ * icingacli web serve --port=8080
+ * icingacli web serve --listen=127.0.0.1:8080 ./public
+ */
+ public function serveAction()
+ {
+ $fork = $this->params->get('daemonize');
+ $listen = $this->params->get('listen');
+ $port = $this->params->get('port');
+ $documentRoot = $this->params->shift();
+ if ($listen === null) {
+ $socket = $port === null ? $this->params->shift() : '0.0.0.0:' . $port;
+ } else {
+ $socket = $listen;
+ }
+
+ if ($socket === null) {
+ $socket = $this->Config()->get('standalone', 'listen', '0.0.0.0:80');
+ }
+ if ($documentRoot === null) {
+ $documentRoot = Icinga::app()->getBaseDir('public');
+ if (! file_exists($documentRoot) || ! is_dir($documentRoot)) {
+ throw new IcingaException('Document root directory is required');
+ }
+ }
+ $documentRoot = realpath($documentRoot);
+
+ if ($fork) {
+ $this->forkAndExit();
+ }
+ echo "Serving Icinga Web 2 from directory $documentRoot and listening on $socket\n";
+
+ // TODO: Store webserver log, switch uid, log index.php includes, pid file
+ pcntl_exec(
+ readlink('/proc/self/exe'),
+ ['-S', $socket, '-t', $documentRoot, Icinga::app()->getLibraryDir('/Icinga/Application/webrouter.php')]
+ );
+ }
+
+ public function stopAction()
+ {
+ // TODO: No, that's NOT what we want
+ $prog = readlink('/proc/self/exe');
+ `killall $prog`;
+ }
+
+ protected function forkAndExit()
+ {
+ $pid = pcntl_fork();
+ if ($pid == -1) {
+ throw new IcingaException('Could not fork');
+ } elseif ($pid) {
+ echo $this->screen->colorize('[OK]')
+ . " Icinga Web server forked successfully\n";
+ fclose(STDIN);
+ fclose(STDOUT);
+ fclose(STDERR);
+ exit;
+ // pcntl_wait($status);
+ } else {
+ // child
+
+ // Replace console with /dev/null by first freeing the (lowest possible) FDs 0, 1 and 2
+ // and then opening /dev/null once for every one of them (open(2) chooses the lowest free FD).
+
+ fclose(STDIN);
+ fclose(STDOUT);
+ fclose(STDERR);
+
+ fopen('/dev/null', 'rb');
+ fopen('/dev/null', 'wb');
+ fopen('/dev/null', 'wb');
+ }
+ }
+}