diff options
Diffstat (limited to 'application/clicommands')
-rw-r--r-- | application/clicommands/AutocompleteCommand.php | 120 | ||||
-rw-r--r-- | application/clicommands/HelpCommand.php | 43 | ||||
-rw-r--r-- | application/clicommands/ModuleCommand.php | 228 | ||||
-rw-r--r-- | application/clicommands/VersionCommand.php | 55 | ||||
-rw-r--r-- | application/clicommands/WebCommand.php | 101 |
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'); + } + } +} |