diff --git a/application/forms/IcingaHostForm.php b/application/forms/IcingaHostForm.php index e86ea784..ec714715 100644 --- a/application/forms/IcingaHostForm.php +++ b/application/forms/IcingaHostForm.php @@ -97,6 +97,17 @@ class IcingaHostForm extends DirectorObjectForm $this->addHidden('command_endpoint_id', null); $this->setSentValue('command_endpoint_id', null); + + $settings = $this->object->getConnection()->settings(); + if ($settings->get('feature_custom_endpoint') === 'y' && ! $this->isTemplate()) { + $this->addElement('text', 'custom_endpoint_name', [ + 'label' => $this->translate('Custom Endpoint Name'), + 'description' => $this->translate( + 'Use a different name for the generated endpoint object than the host name' + . ' and add a custom variable to allow services setting the correct command endpoint.' + ), + ]); + } } else { if ($this->isTemplate()) { $this->addElement('select', 'command_endpoint_id', [ @@ -123,6 +134,7 @@ class IcingaHostForm extends DirectorObjectForm 'master_should_connect', 'accept_config', 'command_endpoint_id', + 'custom_endpoint_name', 'api_key', ]; $this->addDisplayGroup($elements, 'clustering', [ diff --git a/application/forms/SettingsForm.php b/application/forms/SettingsForm.php index 0c1ebf6f..f6ba654b 100644 --- a/application/forms/SettingsForm.php +++ b/application/forms/SettingsForm.php @@ -105,6 +105,18 @@ class SettingsForm extends DirectorForm )); } + $this->addBoolean('feature_custom_endpoint', [ + 'label' => $this->translate('Feature: Custom Endpoint Name'), + 'description' => $this->translate( + 'Enabled the feature for custom endpoint names,' + . ' where you can choose a different name for the generated endpoint object.' + . ' This uses some Icinga config snippets and a special custom variable.' + . ' Please do NOT enable this, unless you really need divergent endpoint names!' + ), + 'value' => $settings->getStoredValue('feature_custom_endpoint') + ]); + + $this->addElement('select', 'config_format', array( 'label' => $this->translate('Configuration format'), 'multiOptions' => $this->eventuallyConfiguredEnum( diff --git a/library/Director/IcingaConfig/AgentWizard.php b/library/Director/IcingaConfig/AgentWizard.php index 53beecd9..aceddb1e 100644 --- a/library/Director/IcingaConfig/AgentWizard.php +++ b/library/Director/IcingaConfig/AgentWizard.php @@ -126,11 +126,6 @@ class AgentWizard $this->ticket = $ticket; } - protected function getCertName() - { - return $this->host->getObjectName(); - } - protected function loadPowershellModule() { return $this->getContribFile('windows-agent-installer/Icinga2Agent.psm1'); @@ -142,7 +137,7 @@ class AgentWizard . "\n\n" . 'exit Icinga2AgentModule `' . "\n " . $this->renderPowershellParameters([ - 'AgentName' => $this->getCertName(), + 'AgentName' => $this->host->getEndpointName(), 'Ticket' => $this->getTicket(), 'ParentZone' => $this->getParentZone()->getObjectName(), 'ParentEndpoints' => array_keys($this->getParentEndpoints()), @@ -272,7 +267,7 @@ class AgentWizard } return $this->replaceBashTemplate($script, [ - 'ICINGA2_NODENAME' => $this->getCertName(), + 'ICINGA2_NODENAME' => $this->host->getEndpointName(), 'ICINGA2_CA_TICKET' => $this->getTicket(), 'ICINGA2_PARENT_ZONE' => $this->getParentZone()->getObjectName(), 'ICINGA2_PARENT_ENDPOINTS' => $endpoints, diff --git a/library/Director/Objects/IcingaHost.php b/library/Director/Objects/IcingaHost.php index d42ab6a1..95a74c08 100644 --- a/library/Director/Objects/IcingaHost.php +++ b/library/Director/Objects/IcingaHost.php @@ -9,6 +9,7 @@ use Icinga\Module\Director\Db; use Icinga\Module\Director\DirectorObject\Automation\ExportInterface; use Icinga\Module\Director\Exception\DuplicateKeyException; use Icinga\Module\Director\IcingaConfig\IcingaConfig; +use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c; use Icinga\Module\Director\IcingaConfig\IcingaLegacyConfigHelper as c1; use Icinga\Module\Director\Objects\Extension\FlappingSupport; use InvalidArgumentException; @@ -55,6 +56,7 @@ class IcingaHost extends IcingaObject implements ExportInterface 'has_agent' => null, 'master_should_connect' => null, 'accept_config' => null, + 'custom_endpoint_name' => null, 'api_key' => null, 'template_choice_id' => null, ); @@ -215,7 +217,8 @@ class IcingaHost extends IcingaObject implements ExportInterface return; } - $name = $this->object_name; + $name = $this->getEndpointName(); + if (IcingaEndpoint::exists($name, $this->connection)) { return; } @@ -249,6 +252,37 @@ class IcingaHost extends IcingaObject implements ExportInterface $config->configFile($pre . 'agent_zones')->addObject($zone); } + protected function renderCustom_endpoint_name() + { + // When feature flag feature_custom_endpoint is enabled, render custom var + if ($this->connection->settings()->get('feature_custom_endpoint') === 'y') { + return c::renderKeyValue( + 'vars._director_custom_endpoint_name', + c::renderPhpValue($this->get('custom_endpoint_name')) + ); + } + + return ''; + } + + /** + * Returns the hostname or custom endpoint name of the Icinga agent + * + * @return string + */ + public function getEndpointName() + { + $name = $this->getObjectName(); + + if ($this->connection->settings()->get('feature_custom_endpoint') === 'y') { + if (($customName = $this->get('custom_endpoint_name')) !== null) { + $name = $customName; + } + } + + return $name; + } + public function getAgentListenPort() { $conn = $this->connection; diff --git a/library/Director/Objects/IcingaService.php b/library/Director/Objects/IcingaService.php index 18ac5b0f..8f813bca 100644 --- a/library/Director/Objects/IcingaService.php +++ b/library/Director/Objects/IcingaService.php @@ -571,7 +571,22 @@ class IcingaService extends IcingaObject implements ExportInterface } if ($this->get('use_agent') === 'y') { - return $output . c::renderKeyValue('command_endpoint', 'host_name'); + // When feature flag feature_custom_endpoint is enabled, render additional code + if ($this->connection->settings()->get('feature_custom_endpoint') === 'y') { + return $output . " + // Set command_endpoint dynamically with Director + if (!host) { + var host = get_host(host_name) + } + if (host.vars._director_custom_endpoint_name) { + command_endpoint = host.vars._director_custom_endpoint_name + } else { + command_endpoint = host_name + } +"; + } else { + return $output . c::renderKeyValue('command_endpoint', 'host_name'); + } } elseif ($this->get('use_agent') === 'n') { return $output . c::renderKeyValue('command_endpoint', c::renderPhpValue(null)); } else { diff --git a/library/Director/Settings.php b/library/Director/Settings.php index 274e5991..d3e09870 100644 --- a/library/Director/Settings.php +++ b/library/Director/Settings.php @@ -26,6 +26,7 @@ class Settings 'self-service/resolve_parent_host' => '0', 'self-service/global_zones' => ['director-global'], 'ignore_bug7530' => 'n', + 'feature_custom_endpoint' => 'n', // 'experimental_features' => null, // 'allow' // 'master_zone' => null, ]; diff --git a/library/Director/Web/SelfService.php b/library/Director/Web/SelfService.php index dae0bb92..b379c9f4 100644 --- a/library/Director/Web/SelfService.php +++ b/library/Director/Web/SelfService.php @@ -223,10 +223,9 @@ class SelfService ))); $cc->addTitle('Agent deployment instructions'); - $certname = $host->getObjectName(); try { - $ticket = $this->api->getTicket($host->getObjectName()); + $ticket = $this->api->getTicket($host->getEndpointName()); $wizard = new AgentWizard($host); $wizard->setTicket($ticket); } catch (Exception $e) { @@ -278,7 +277,7 @@ class SelfService public function handleLegacyAgentDownloads($os) { $wizard = new AgentWizard($this->host); - $wizard->setTicket($this->api->getTicket($this->host->getObjectName())); + $wizard->setTicket($this->api->getTicket($this->host->getEndpointName())); switch ($os) { case 'windows-kickstart': diff --git a/schema/mysql-migrations/upgrade_176.sql b/schema/mysql-migrations/upgrade_176.sql new file mode 100644 index 00000000..9913c116 --- /dev/null +++ b/schema/mysql-migrations/upgrade_176.sql @@ -0,0 +1,6 @@ +ALTER TABLE icinga_host ADD COLUMN custom_endpoint_name VARCHAR(255) DEFAULT NULL AFTER accept_config; +ALTER TABLE branched_icinga_host ADD COLUMN custom_endpoint_name VARCHAR(255) DEFAULT NULL AFTER accept_config; + +INSERT INTO director_schema_migration + (schema_version, migration_time) + VALUES ('176', NOW()); diff --git a/schema/mysql.sql b/schema/mysql.sql index 8042791c..6efda055 100644 --- a/schema/mysql.sql +++ b/schema/mysql.sql @@ -555,6 +555,7 @@ CREATE TABLE icinga_host ( has_agent ENUM('y', 'n') DEFAULT NULL, master_should_connect ENUM('y', 'n') DEFAULT NULL, accept_config ENUM('y', 'n') DEFAULT NULL, + custom_endpoint_name VARCHAR(255) DEFAULT NULL, api_key VARCHAR(40) DEFAULT NULL, template_choice_id INT(10) UNSIGNED DEFAULT NULL, PRIMARY KEY (id), @@ -1977,6 +1978,7 @@ CREATE TABLE branched_icinga_host ( has_agent ENUM('y', 'n') DEFAULT NULL, master_should_connect ENUM('y', 'n') DEFAULT NULL, accept_config ENUM('y', 'n') DEFAULT NULL, + custom_endpoint_name VARCHAR(255) DEFAULT NULL, api_key VARCHAR(40) DEFAULT NULL, imports TEXT DEFAULT NULL, @@ -2393,4 +2395,4 @@ CREATE TABLE branched_icinga_dependency ( INSERT INTO director_schema_migration (schema_version, migration_time) - VALUES (175, NOW()); + VALUES (176, NOW()); diff --git a/schema/pgsql-migrations/upgrade_176.sql b/schema/pgsql-migrations/upgrade_176.sql new file mode 100644 index 00000000..eadcb18a --- /dev/null +++ b/schema/pgsql-migrations/upgrade_176.sql @@ -0,0 +1,6 @@ +ALTER TABLE icinga_host ADD COLUMN custom_endpoint_name character varying(255) DEFAULT NULL; +ALTER TABLE branched_icinga_host ADD COLUMN custom_endpoint_name character varying(255) DEFAULT NULL; + +INSERT INTO director_schema_migration + (schema_version, migration_time) + VALUES ('176', NOW()); diff --git a/schema/pgsql.sql b/schema/pgsql.sql index 92019668..44970d39 100644 --- a/schema/pgsql.sql +++ b/schema/pgsql.sql @@ -690,6 +690,7 @@ CREATE TABLE icinga_host ( has_agent enum_boolean DEFAULT NULL, master_should_connect enum_boolean DEFAULT NULL, accept_config enum_boolean DEFAULT NULL, + custom_endpoint_name character varying(255) DEFAULT NULL, api_key character varying(40) DEFAULT NULL, template_choice_id int DEFAULT NULL, PRIMARY KEY (id), @@ -2298,6 +2299,7 @@ CREATE TABLE branched_icinga_host ( has_agent enum_boolean DEFAULT NULL, master_should_connect enum_boolean DEFAULT NULL, accept_config enum_boolean DEFAULT NULL, + custom_endpoint_name character varying(255) DEFAULT NULL, api_key character varying(40) DEFAULT NULL, -- template_choice character varying(255) DEFAULT NULL, -- TODO: Forbid them! @@ -2739,4 +2741,4 @@ CREATE INDEX branched_dependency_search_object_name ON branched_icinga_dependenc INSERT INTO director_schema_migration (schema_version, migration_time) - VALUES (175, NOW()); + VALUES (176, NOW());