IcingaConfig: render host templates to all...

...non-global zones, instead of the default global zone

refs #2410
This commit is contained in:
Thomas Gelf 2023-09-21 14:02:52 +02:00 committed by raviks789
parent 63a3e6a1ec
commit 4d050834db
7 changed files with 90 additions and 11 deletions

View File

@ -26,6 +26,7 @@ This version hasn't been released yet
### Icinga Configuration
* FEATURE: render fallback template for IfW 1.11 for Icinga < 2.14 (#2776)
* FEATURE: render host templates to all non-global zones per default (#2410)
* FIX: render Set Services to individual zones where required (#1589, #2356)
* FIX: special characters like & and | caused trouble in filters (#2667)

View File

@ -25,6 +25,9 @@ class IcingaConfig
protected $zoneMap = array();
/** @var ?array Exists for caching reasons at rendering time */
protected $nonGlobalZones = null;
protected $lastActivityChecksum;
/** @var \Zend_Db_Adapter_Abstract */
@ -349,6 +352,15 @@ class IcingaConfig
return $this->zoneMap[$id];
}
public function listNonGlobalZones(): array
{
if ($this->nonGlobalZones === null) {
$this->nonGlobalZones = array_values($this->connection->enumNonglobalZones());
}
return $this->nonGlobalZones;
}
/**
* @return self
*/

View File

@ -309,6 +309,20 @@ class IcingaHost extends IcingaObject implements ExportInterface
}
}
protected function rendersConditionalTemplate(): bool
{
return $this->getRenderingZone() === self::ALL_NON_GLOBAL_ZONES;
}
protected function getDefaultZone(IcingaConfig $config = null)
{
if ($this->isTemplate()) {
return self::ALL_NON_GLOBAL_ZONES;
}
return parent::getDefaultZone();
}
public function beforeDelete()
{
foreach ($this->fetchServices() as $service) {

View File

@ -27,6 +27,7 @@ use RuntimeException;
abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
{
const RESOLVE_ERROR = '(unable to resolve)';
const ALL_NON_GLOBAL_ZONES = '(all non-global zones)';
protected $keyName = 'object_name';
@ -1800,9 +1801,21 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
return;
}
$config->configFile(
'zones.d/' . $this->getRenderingZone($config) . '/' . $this->getRenderingFilename()
)->addObject($this);
foreach ($this->getRenderingZones($config) as $zone) {
$config->configFile(
'zones.d/' . $zone . '/' . $this->getRenderingFilename()
)->addObject($this);
}
}
protected function getRenderingZones(IcingaConfig $config): array
{
$zone = $this->getRenderingZone($config);
if ($zone === self::ALL_NON_GLOBAL_ZONES) {
return $config->listNonGlobalZones();
}
return [$zone];
}
public function getRenderingFilename()
@ -2181,7 +2194,12 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
protected function renderSuffix()
{
return "}\n\n";
$prefix = '';
if ($this->rendersConditionalTemplate()) {
$prefix = '} ';
}
return "$prefix}\n\n";
}
protected function renderLegacySuffix()
@ -2406,14 +2424,25 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
protected function renderObjectHeader()
{
$prefix = '';
$renderedName = c::renderString($this->getObjectName());
if ($this->rendersConditionalTemplate()) {
$prefix = sprintf('if (! get_template(%s, %s)) { ', $this->getType(), $renderedName);
}
return sprintf(
"%s %s %s {\n",
"%s%s %s %s {\n",
$prefix,
$this->getObjectTypeName(),
$this->getType(),
c::renderString($this->getObjectName())
$renderedName
);
}
protected function rendersConditionalTemplate(): bool
{
return false;
}
public function getLegacyObjectType()
{
return strtolower($this->getType());

View File

@ -384,6 +384,11 @@ class IcingaService extends IcingaObject implements ExportInterface
}
}
protected function rendersConditionalTemplate(): bool
{
return $this->getRenderingZone() === self::ALL_NON_GLOBAL_ZONES;
}
/**
* @return bool
*/
@ -578,11 +583,22 @@ class IcingaService extends IcingaObject implements ExportInterface
protected function getDefaultZone(IcingaConfig $config = null)
{
// Hint: this isn't possible yet, as we're unable to render dependent apply rules to multiple zones as well
// if ($this->isTemplate()) {
// return self::ALL_NON_GLOBAL_ZONES;
// }
if ($this->get('host_id') === null) {
return parent::getDefaultZone();
} else {
return $this->getRelatedObject('host', $this->get('host_id'))
$zone = $this->getRelatedObject('host', $this->get('host_id'))
->getRenderingZone($config);
// Hint: this avoids problems with host templates rendered to all non-global zones
if ($zone === self::ALL_NON_GLOBAL_ZONES) {
$zone = $this->connection->getDefaultGlobalZoneName();
}
return $zone;
}
}

View File

@ -264,9 +264,10 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
}
$this->copyVarsToService($service);
$zone = $service->getRenderingZone($config);
$file = $this->getConfigFileWithHeader($config, $zone, $files);
$file->addObject($service);
foreach ($service->getRenderingZones($config) as $serviceZone) {
$file = $this->getConfigFileWithHeader($config, $serviceZone, $files);
$file->addObject($service);
}
}
if (empty($files)) {

View File

@ -396,10 +396,16 @@ class IcingaHostTest extends BaseTestCase
$host->object_type = 'template';
$host->zone_id = null;
$zone = $this->newObject('zone', '___TEST___zone2');
$zone->store($db);
$config = new IcingaConfig($db);
$host->renderToConfig($config);
$this->assertEquals(
array('zones.d/director-global/host_templates.conf'),
[
'zones.d/___TEST___zone/host_templates.conf',
'zones.d/___TEST___zone2/host_templates.conf',
],
$config->getFileNames()
);
}